blob: 26ff6b7380cb211ea2544e6076d5c7a5c82b90e7 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko8580e852016-08-19 19:11:48 +03003# ABI Compliance Checker (ABICC) 1.99.24
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey 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 Ponomarenko8580e852016-08-19 19:11:48 +030063my $TOOL_VERSION = "1.99.24";
64my $ABI_DUMP_VERSION = "3.3";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030088$SkipHeadersPath, $CxxCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CxxIncompat,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030093$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030095$DisableQuickEmptyReport, $SkipTypedefUncover, $MinGWCompat, $SkipUnidentified,
96$DisableConstantsCheck, $SkipAddedConstants, $SkipRemovedConstants);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300149my %HomePage = (
150 "Dev"=>"https://github.com/lvc/abi-compliance-checker",
151 "Wiki"=>"https://lvc.github.io/abi-compliance-checker/"
152);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400154my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400155A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300156Copyright (C) 2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157License: GNU LGPL or GNU GPL
158
159Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400160Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400161
162OLD.xml and NEW.xml are XML-descriptors:
163
164 <version>
165 1.0
166 </version>
167
168 <headers>
169 /path/to/headers/
170 </headers>
171
172 <libs>
173 /path/to/libraries/
174 </libs>
175
176More info: $CmdName --help\n";
177
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400178if($#ARGV==-1)
179{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400180 printMsg("INFO", $ShortUsage);
181 exit(0);
182}
183
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400184GetOptions("h|help!" => \$Help,
185 "i|info!" => \$InfoMsg,
186 "v|version!" => \$ShowVersion,
187 "dumpversion!" => \$DumpVersion,
188# general options
189 "l|lib|library=s" => \$TargetLibraryName,
190 "d1|old|o=s" => \$Descriptor{1}{"Path"},
191 "d2|new|n=s" => \$Descriptor{2}{"Path"},
192 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 "app|application=s" => \$AppPath,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300195 "static|static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400196 "gcc-path|cross-gcc=s" => \$CrossGcc,
197 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
198 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400199 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300200 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
201 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400202 "s|strict!" => \$StrictCompat,
203 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300204 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400205 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300206 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300207 "disable-constants-check!" => \$DisableConstantsCheck,
208 "skip-added-constants!" => \$SkipAddedConstants,
209 "skip-removed-constants!" => \$SkipRemovedConstants,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400210 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400211 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400212 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400214 "show-retval!" => \$ShowRetVal,
215 "use-dumps!" => \$UseDumps,
216 "nostdinc!" => \$NoStdInc,
217 "dump-system=s" => \$DumpSystem,
218 "sysinfo=s" => \$TargetSysInfo,
219 "cmp-systems!" => \$CmpSystems,
220 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "ext|extended!" => \$ExtendedCheck,
222 "q|quiet!" => \$Quiet,
223 "stdout!" => \$StdOut,
224 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400225 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400226 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400228 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400229 "binary|bin|abi!" => \$BinaryOnly,
230 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400231 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300232 "count-symbols=s" => \$CountSymbols,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300233 "old-style!" => \$OldStyle,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234# other options
235 "test!" => \$TestTool,
236 "test-dump!" => \$TestDump,
237 "debug!" => \$Debug,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300238 "cpp-compatible!" => \$CxxCompat,
239 "cxx-incompatible|cpp-incompatible!" => \$CxxIncompat,
240 "mingw-compatible!" => \$MinGWCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400241 "p|params=s" => \$ParamNamesPath,
242 "relpath1|relpath=s" => \$RelativeDirectory{1},
243 "relpath2=s" => \$RelativeDirectory{2},
244 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400245 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400246 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "bin-report-path=s" => \$BinaryReportPath,
248 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400249 "log-path=s" => \$LoggingPath,
250 "log1-path=s" => \$OutputLogPath{1},
251 "log2-path=s" => \$OutputLogPath{2},
252 "logging-mode=s" => \$LogMode,
253 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300254 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400255 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400256 "extra-info=s" => \$ExtraInfo,
257 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400258 "force!" => \$Force,
259 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400260 "tolerant!" => \$Tolerant,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300261 "skip-unidentified!" => \$SkipUnidentified,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400262 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400263 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300264 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400265 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300266 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
267 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300268 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300269 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400270) or ERR_MESSAGE();
271
272sub ERR_MESSAGE()
273{
274 printMsg("INFO", "\n".$ShortUsage);
275 exit($ERROR_CODE{"Error"});
276}
277
278my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
279my $SLIB_TYPE = $LIB_TYPE;
280if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
281{ # show as "shared" library
282 $SLIB_TYPE = "shared";
283}
284my $LIB_EXT = getLIB_EXT($OSgroup);
285my $AR_EXT = getAR_EXT($OSgroup);
286my $BYTE_SIZE = 8;
287my $COMMON_LOG_PATH = "logs/run.log";
288
289my $HelpMessage="
290NAME:
291 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400292 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400293
294DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400295 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400296 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
297 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
298 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
299 and/or source-level compatibility: changes in calling stack, v-table changes,
300 removed symbols, renamed fields, etc. Binary incompatibility may result in
301 crashing or incorrect behavior of applications built with an old version of
302 a library if they run on a new one. Source incompatibility may result in
303 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400304
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400305 The tool is intended for developers of software libraries and maintainers
306 of operating systems who are interested in ensuring backward compatibility,
307 i.e. allow old applications to run or to be recompiled with newer library
308 versions.
309
310 Also the tool can be used by ISVs for checking applications portability to
311 new library versions. Found issues can be taken into account when adapting
312 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400313
314 This tool is free software: you can redistribute it and/or modify it
315 under the terms of the GNU LGPL or GNU GPL.
316
317USAGE:
318 $CmdName [options]
319
320EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400321 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400322
323 OLD.xml and NEW.xml are XML-descriptors:
324
325 <version>
326 1.0
327 </version>
328
329 <headers>
330 /path1/to/header(s)/
331 /path2/to/header(s)/
332 ...
333 </headers>
334
335 <libs>
336 /path1/to/library(ies)/
337 /path2/to/library(ies)/
338 ...
339 </libs>
340
341INFORMATION OPTIONS:
342 -h|-help
343 Print this help.
344
345 -i|-info
346 Print complete info.
347
348 -v|-version
349 Print version information.
350
351 -dumpversion
352 Print the tool version ($TOOL_VERSION) and don't do anything else.
353
354GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400355 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400356 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400357
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400358 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400359 Descriptor of 1st (old) library version.
360 It may be one of the following:
361
362 1. XML-descriptor (VERSION.xml file):
363
364 <version>
365 1.0
366 </version>
367
368 <headers>
369 /path1/to/header(s)/
370 /path2/to/header(s)/
371 ...
372 </headers>
373
374 <libs>
375 /path1/to/library(ies)/
376 /path2/to/library(ies)/
377 ...
378 </libs>
379
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300380 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400381
382 2. ABI dump generated by -dump option
383 3. Directory with headers and/or $SLIB_TYPE libraries
384 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400385
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300386 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400387 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400388
389 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400390 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400391
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400392 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400393 Descriptor of 2nd (new) library version.
394
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400395 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400396 Create library ABI dump for the input XML descriptor. You can
397 transfer it anywhere and pass instead of the descriptor. Also
398 it can be used for debugging the tool.
399
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300400 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400401
402sub HELP_MESSAGE() {
403 printMsg("INFO", $HelpMessage."
404MORE INFO:
405 $CmdName --info\n");
406}
407
408sub INFO_MESSAGE()
409{
410 printMsg("INFO", "$HelpMessage
411EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400412 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300413 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414 for portability to the new library version.
415
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300416 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417 Check static libraries instead of the shared ones. The <libs> section
418 of the XML-descriptor should point to static libraries location.
419
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300420 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421 Path to the cross GCC compiler to use instead of the usual (host) GCC.
422
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300423 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400424 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300425
426 -gcc-options OPTS
427 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400428
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400429 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400430 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400431 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400434 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200435 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400436
437 In general case you should specify it in the XML-descriptor:
438 <version>
439 VERSION
440 </version>
441
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400442 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400443 Specify 2nd library version outside the descriptor.
444
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400445 -vnum NUM
446 Specify the library version in the generated ABI dump. The <version> section
447 of the input XML descriptor will be overwritten in this case.
448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400449 -s|-strict
450 Treat all compatibility warnings as problems. Add a number of \"Low\"
451 severity problems to the return value of the tool.
452
453 -headers-only
454 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
455 provide a low quality compatibility report with false positives and
456 without detecting of added/removed symbols.
457
458 Alternatively you can write \"none\" word to the <libs> section
459 in the XML-descriptor:
460 <libs>
461 none
462 </libs>
463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400464 -show-retval
465 Show the symbol's return type in the report.
466
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400467 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300468 This option allows to specify a file with a list of symbols (mangled
469 names in C++) that should be checked. Other symbols will not be checked.
470
471 -types-list PATH
472 This option allows to specify a file with a list of types that should
473 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400474
475 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300476 The list of symbols that should not be checked.
477
478 -skip-types PATH
479 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400480
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300481 -disable-constants-check
482 Do not check for changes in constants.
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300483
484 -skip-added-constants
485 Do not detect added constants.
486
487 -skip-removed-constants
488 Do not detect removed constants.
489
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400490 -headers-list PATH
491 The file with a list of headers, that should be checked/dumped.
492
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400493 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400494 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400495
496 -header NAME
497 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400498
499 -use-dumps
500 Make dumps for two versions of a library and compare dumps. This should
501 increase the performance of the tool and decrease the system memory usage.
502
503 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400504 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400505
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400506 -dump-system NAME -sysroot DIR
507 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400508 create XML descriptors and make ABI dumps for each library. The result
509 set of ABI dumps can be compared (--cmp-systems) with the other one
510 created for other version of operating system in order to check them for
511 compatibility. Do not forget to specify -cross-gcc option if your target
512 system requires some specific version of GCC compiler (different from
513 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400514 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400515
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400516 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400517 The same as the previous option but takes an XML descriptor of the target
518 system as input, where you should describe it:
519
520 /* Primary sections */
521
522 <name>
523 /* Name of the system */
524 </name>
525
526 <headers>
527 /* The list of paths to header files and/or
528 directories with header files, one per line */
529 </headers>
530
531 <libs>
532 /* The list of paths to shared libraries and/or
533 directories with shared libraries, one per line */
534 </libs>
535
536 /* Optional sections */
537
538 <search_headers>
539 /* List of directories to be searched
540 for header files to automatically
541 generate include paths, one per line */
542 </search_headers>
543
544 <search_libs>
545 /* List of directories to be searched
546 for shared libraries to resolve
547 dependencies, one per line */
548 </search_libs>
549
550 <tools>
551 /* List of directories with tools used
552 for analysis (GCC toolchain), one per line */
553 </tools>
554
555 <cross_prefix>
556 /* GCC toolchain prefix.
557 Examples:
558 arm-linux-gnueabi
559 arm-none-symbianelf */
560 </cross_prefix>
561
562 <gcc_options>
563 /* Additional GCC options, one per line */
564 </gcc_options>
565
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400566 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300567 This option should be used with -dump-system option to dump
568 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400569
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400570 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300571 Compare two ABI dumps of a system. Create compatibility reports for
572 each system library and the common HTML report including the summary
573 of test results for all checked libraries.
574
575 Summary report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400576 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400579 The file with a list of libraries, that should be dumped by
580 the -dump-system option or should be checked by the -cmp-systems option.
581
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400582 -ext|-extended
583 If your library A is supposed to be used by other library B and you
584 want to control the ABI of B, then you should enable this option. The
585 tool will check for changes in all data types, even if they are not
586 used by any function in the library A. Such data types are not part
587 of the A library ABI, but may be a part of the ABI of the B library.
588
589 The short scheme is:
590 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
591
592 -q|-quiet
593 Print all messages to the file instead of stdout and stderr.
594 Default path (can be changed by -log-path option):
595 $COMMON_LOG_PATH
596
597 -stdout
598 Print analysis results (compatibility reports and ABI dumps) to stdout
599 instead of creating a file. This would allow piping data to other programs.
600
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400601 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400602 Change format of compatibility report.
603 Formats:
604 htm - HTML format (default)
605 xml - XML format
606
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400607 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400608 Change format of ABI dump.
609 Formats:
610 perl - Data::Dumper format (default)
611 xml - XML format
612
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400613 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400614 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400615
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400616 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400617 Set library language (C or C++). You can use this option if the tool
618 cannot auto-detect a language. This option may be useful for checking
619 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400620
621 -arch ARCH
622 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
623 ect.). The option is useful if the tool cannot detect correct architecture
624 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400625
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400626 -binary|-bin|-abi
627 Show \"Binary\" compatibility problems only.
628 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400629 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400630
631 -source|-src|-api
632 Show \"Source\" compatibility problems only.
633 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400634 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400635
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400636 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400637 The maximum number of affected symbols listed under the description
638 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300639
640 -count-symbols PATH
641 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300642
643 -old-style
644 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400645
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400646OTHER OPTIONS:
647 -test
648 Run internal tests. Create two binary incompatible versions of a sample
649 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300650 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400651
652 -test-dump
653 Test ability to create, read and compare ABI dumps.
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400655 -debug
656 Debugging mode. Print debug info on the screen. Save intermediate
657 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400658 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400660 Also consider using --dump option for debugging the tool.
661
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662 -cpp-compatible
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300663 Do nothing.
664
665 -cxx-incompatible
666 Set this option if input C header files use C++ keywords. The tool
667 will try to replace such keywords at preprocessor stage and replace
668 them back in the final TU dump.
669
670 -mingw-compatible
671 If input header files are compatible with the MinGW GCC compiler,
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300672 then you can tell the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400675 Path to file with the function parameter names. It can be used
676 for improving report view if the library header files have no
677 parameter names. File format:
678
679 func1;param1;param2;param3 ...
680 func2;param1;param2;param3 ...
681 ...
682
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 -relpath PATH
684 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400685 for dumping the library ABI (see -dump option).
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -relpath1 PATH
688 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -relpath2 PATH
691 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400694 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400698 -sort
699 Enable sorting of data in ABI dumps.
700
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400701 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400702 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400703 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400705
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400706 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400707 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400708 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400709 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400710
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400711 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712 Path to \"Source\" compatibility report.
713 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400715
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717 Log path for all messages.
718 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400721 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400722 Log path for 1st version of a library.
723 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400724 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400725
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400727 Log path for 2nd version of a library.
728 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400729 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400730
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732 Change logging mode.
733 Modes:
734 w - overwrite old logs (default)
735 a - append old logs
736 n - do not write any logs
737
738 -list-affected
739 Generate file with the list of incompatible
740 symbols beside the HTML compatibility report.
741 Use 'c++filt \@file' command from GNU binutils
742 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400743 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400744 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400745 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400746
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400747 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 The component name in the title and summary of the HTML report.
749 Default:
750 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300751
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300752 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400753 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400754 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400755
756 -extra-info DIR
757 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400758
759 -extra-dump
760 Create extended ABI dump containing all symbols
761 from the translation unit.
762
763 -force
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300764 Try to enable this option if the tool checked zero
765 types and symbols in header files.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400766
767 -tolerance LEVEL
768 Apply a set of heuristics to successfully compile input
769 header files. You can enable several tolerance levels by
770 joining them into one string (e.g. 13, 124, etc.).
771 Levels:
772 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
773 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900774 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400775 4 - skip headers included by others
776
777 -tolerant
778 Enable highest tolerance level [1234].
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300779
780 -skip-unidentified
781 Skip header files in 'headers' and 'include_preamble' sections
782 of the XML descriptor that cannot be found. This is useful if
783 you are trying to use the same descriptor for different targets.
784
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400785 -check
786 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400787
788 -quick
789 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300790
791 -disable-quick-empty-report
792 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400793
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300794 -skip-internal-symbols PATTERN
795 Do not check symbols matched by the pattern.
796
797 -skip-internal-types PATTERN
798 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300799
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300800 -skip-typedef-uncover
801 Do not report a problem if type is covered or
802 uncovered by typedef (useful for broken debug info).
803
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300804 -check-private-abi
805 Check data types from the private part of the ABI when
806 comparing ABI dumps created by the ABI Dumper tool with
807 use of the -public-headers option.
808
809 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400811REPORT:
812 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400813 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400814
815 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400816 logs/LIB_NAME/V1/log.txt
817 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400818
819EXIT CODES:
820 0 - Compatible. The tool has run without any errors.
821 non-zero - Incompatible or the tool has run with errors.
822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400823MORE INFORMATION:
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300824 ".$HomePage{"Wiki"}."
Andrey Ponomarenko868b1352016-09-29 14:13:30 +0300825 ".$HomePage{"Dev"}."\n\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400826}
827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400828my %Operator_Indication = (
829 "not" => "~",
830 "assign" => "=",
831 "andassign" => "&=",
832 "orassign" => "|=",
833 "xorassign" => "^=",
834 "or" => "|",
835 "xor" => "^",
836 "addr" => "&",
837 "and" => "&",
838 "lnot" => "!",
839 "eq" => "==",
840 "ne" => "!=",
841 "lt" => "<",
842 "lshift" => "<<",
843 "lshiftassign" => "<<=",
844 "rshiftassign" => ">>=",
845 "call" => "()",
846 "mod" => "%",
847 "modassign" => "%=",
848 "subs" => "[]",
849 "land" => "&&",
850 "lor" => "||",
851 "rshift" => ">>",
852 "ref" => "->",
853 "le" => "<=",
854 "deref" => "*",
855 "mult" => "*",
856 "preinc" => "++",
857 "delete" => " delete",
858 "vecnew" => " new[]",
859 "vecdelete" => " delete[]",
860 "predec" => "--",
861 "postinc" => "++",
862 "postdec" => "--",
863 "plusassign" => "+=",
864 "plus" => "+",
865 "minus" => "-",
866 "minusassign" => "-=",
867 "gt" => ">",
868 "ge" => ">=",
869 "new" => " new",
870 "multassign" => "*=",
871 "divassign" => "/=",
872 "div" => "/",
873 "neg" => "-",
874 "pos" => "+",
875 "memref" => "->*",
876 "compound" => "," );
877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400878my %UnknownOperator;
879
880my %NodeType= (
881 "array_type" => "Array",
882 "binfo" => "Other",
883 "boolean_type" => "Intrinsic",
884 "complex_type" => "Intrinsic",
885 "const_decl" => "Other",
886 "enumeral_type" => "Enum",
887 "field_decl" => "Other",
888 "function_decl" => "Other",
889 "function_type" => "FunctionType",
890 "identifier_node" => "Other",
891 "integer_cst" => "Other",
892 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400893 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400894 "method_type" => "MethodType",
895 "namespace_decl" => "Other",
896 "parm_decl" => "Other",
897 "pointer_type" => "Pointer",
898 "real_cst" => "Other",
899 "real_type" => "Intrinsic",
900 "record_type" => "Struct",
901 "reference_type" => "Ref",
902 "string_cst" => "Other",
903 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400904 "template_type_parm" => "TemplateParam",
905 "typename_type" => "TypeName",
906 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400907 "tree_list" => "Other",
908 "tree_vec" => "Other",
909 "type_decl" => "Other",
910 "union_type" => "Union",
911 "var_decl" => "Other",
912 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400913 "nop_expr" => "Other", #
914 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400915 "offset_type" => "Other" );
916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400917my %CppKeywords_C = map {$_=>1} (
918 # C++ 2003 keywords
919 "public",
920 "protected",
921 "private",
922 "default",
923 "template",
924 "new",
925 #"asm",
926 "dynamic_cast",
927 "auto",
928 "try",
929 "namespace",
930 "typename",
931 "using",
932 "reinterpret_cast",
933 "friend",
934 "class",
935 "virtual",
936 "const_cast",
937 "mutable",
938 "static_cast",
939 "export",
940 # C++0x keywords
941 "noexcept",
942 "nullptr",
943 "constexpr",
944 "static_assert",
945 "explicit",
946 # cannot be used as a macro name
947 # as it is an operator in C++
948 "and",
949 #"and_eq",
950 "not",
951 #"not_eq",
952 "or"
953 #"or_eq",
954 #"bitand",
955 #"bitor",
956 #"xor",
957 #"xor_eq",
958 #"compl"
959);
960
961my %CppKeywords_F = map {$_=>1} (
962 "delete",
963 "catch",
964 "alignof",
965 "thread_local",
966 "decltype",
967 "typeid"
968);
969
970my %CppKeywords_O = map {$_=>1} (
971 "bool",
972 "register",
973 "inline",
974 "operator"
975);
976
977my %CppKeywords_A = map {$_=>1} (
978 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400979 "throw",
980 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400981);
982
983foreach (keys(%CppKeywords_C),
984keys(%CppKeywords_F),
985keys(%CppKeywords_O)) {
986 $CppKeywords_A{$_}=1;
987}
988
989# Header file extensions as described by gcc
990my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
991
992my %IntrinsicMangling = (
993 "void" => "v",
994 "bool" => "b",
995 "wchar_t" => "w",
996 "char" => "c",
997 "signed char" => "a",
998 "unsigned char" => "h",
999 "short" => "s",
1000 "unsigned short" => "t",
1001 "int" => "i",
1002 "unsigned int" => "j",
1003 "long" => "l",
1004 "unsigned long" => "m",
1005 "long long" => "x",
1006 "__int64" => "x",
1007 "unsigned long long" => "y",
1008 "__int128" => "n",
1009 "unsigned __int128" => "o",
1010 "float" => "f",
1011 "double" => "d",
1012 "long double" => "e",
1013 "__float80" => "e",
1014 "__float128" => "g",
1015 "..." => "z"
1016);
1017
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001018my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1019
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001020my %StdcxxMangling = (
1021 "3std"=>"St",
1022 "3std9allocator"=>"Sa",
1023 "3std12basic_string"=>"Sb",
1024 "3std12basic_stringIcE"=>"Ss",
1025 "3std13basic_istreamIcE"=>"Si",
1026 "3std13basic_ostreamIcE"=>"So",
1027 "3std14basic_iostreamIcE"=>"Sd"
1028);
1029
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001030my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001031my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1032
1033my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001034my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001036my %ConstantSuffix = (
1037 "unsigned int"=>"u",
1038 "long"=>"l",
1039 "unsigned long"=>"ul",
1040 "long long"=>"ll",
1041 "unsigned long long"=>"ull"
1042);
1043
1044my %ConstantSuffixR =
1045reverse(%ConstantSuffix);
1046
1047my %OperatorMangling = (
1048 "~" => "co",
1049 "=" => "aS",
1050 "|" => "or",
1051 "^" => "eo",
1052 "&" => "an",#ad (addr)
1053 "==" => "eq",
1054 "!" => "nt",
1055 "!=" => "ne",
1056 "<" => "lt",
1057 "<=" => "le",
1058 "<<" => "ls",
1059 "<<=" => "lS",
1060 ">" => "gt",
1061 ">=" => "ge",
1062 ">>" => "rs",
1063 ">>=" => "rS",
1064 "()" => "cl",
1065 "%" => "rm",
1066 "[]" => "ix",
1067 "&&" => "aa",
1068 "||" => "oo",
1069 "*" => "ml",#de (deref)
1070 "++" => "pp",#
1071 "--" => "mm",#
1072 "new" => "nw",
1073 "delete" => "dl",
1074 "new[]" => "na",
1075 "delete[]" => "da",
1076 "+=" => "pL",
1077 "+" => "pl",#ps (pos)
1078 "-" => "mi",#ng (neg)
1079 "-=" => "mI",
1080 "*=" => "mL",
1081 "/=" => "dV",
1082 "&=" => "aN",
1083 "|=" => "oR",
1084 "%=" => "rM",
1085 "^=" => "eO",
1086 "/" => "dv",
1087 "->*" => "pm",
1088 "->" => "pt",#rf (ref)
1089 "," => "cm",
1090 "?" => "qu",
1091 "." => "dt",
1092 "sizeof"=> "sz"#st
1093);
1094
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001095my %Intrinsic_Keywords = map {$_=>1} (
1096 "true",
1097 "false",
1098 "_Bool",
1099 "_Complex",
1100 "const",
1101 "int",
1102 "long",
1103 "void",
1104 "short",
1105 "float",
1106 "volatile",
1107 "restrict",
1108 "unsigned",
1109 "signed",
1110 "char",
1111 "double",
1112 "class",
1113 "struct",
1114 "union",
1115 "enum"
1116);
1117
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001118my %GlibcHeader = map {$_=>1} (
1119 "aliases.h",
1120 "argp.h",
1121 "argz.h",
1122 "assert.h",
1123 "cpio.h",
1124 "ctype.h",
1125 "dirent.h",
1126 "envz.h",
1127 "errno.h",
1128 "error.h",
1129 "execinfo.h",
1130 "fcntl.h",
1131 "fstab.h",
1132 "ftw.h",
1133 "glob.h",
1134 "grp.h",
1135 "iconv.h",
1136 "ifaddrs.h",
1137 "inttypes.h",
1138 "langinfo.h",
1139 "limits.h",
1140 "link.h",
1141 "locale.h",
1142 "malloc.h",
1143 "math.h",
1144 "mntent.h",
1145 "monetary.h",
1146 "nl_types.h",
1147 "obstack.h",
1148 "printf.h",
1149 "pwd.h",
1150 "regex.h",
1151 "sched.h",
1152 "search.h",
1153 "setjmp.h",
1154 "shadow.h",
1155 "signal.h",
1156 "spawn.h",
1157 "stdarg.h",
1158 "stdint.h",
1159 "stdio.h",
1160 "stdlib.h",
1161 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001162 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001163 "tar.h",
1164 "termios.h",
1165 "time.h",
1166 "ulimit.h",
1167 "unistd.h",
1168 "utime.h",
1169 "wchar.h",
1170 "wctype.h",
1171 "wordexp.h" );
1172
1173my %GlibcDir = map {$_=>1} (
1174 "arpa",
1175 "bits",
1176 "gnu",
1177 "netinet",
1178 "net",
1179 "nfs",
1180 "rpc",
1181 "sys",
1182 "linux" );
1183
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001184my %WinHeaders = map {$_=>1} (
1185 "dos.h",
1186 "process.h",
1187 "winsock.h",
1188 "config-win.h",
1189 "mem.h",
1190 "windows.h",
1191 "winsock2.h",
1192 "crtdbg.h",
1193 "ws2tcpip.h"
1194);
1195
1196my %ObsoleteHeaders = map {$_=>1} (
1197 "iostream.h",
1198 "fstream.h"
1199);
1200
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001201my %AlienHeaders = map {$_=>1} (
1202 # Solaris
1203 "thread.h",
1204 "sys/atomic.h",
1205 # HPUX
1206 "sys/stream.h",
1207 # Symbian
1208 "AknDoc.h",
1209 # Atari ST
1210 "ext.h",
1211 "tos.h",
1212 # MS-DOS
1213 "alloc.h",
1214 # Sparc
1215 "sys/atomic.h"
1216);
1217
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001218my %ConfHeaders = map {$_=>1} (
1219 "atomic",
1220 "conf.h",
1221 "config.h",
1222 "configure.h",
1223 "build.h",
1224 "setup.h"
1225);
1226
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001227my %LocalIncludes = map {$_=>1} (
1228 "/usr/local/include",
1229 "/usr/local" );
1230
1231my %OS_AddPath=(
1232# These paths are needed if the tool cannot detect them automatically
1233 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001234 "include"=>[
1235 "/Library",
1236 "/Developer/usr/include"
1237 ],
1238 "lib"=>[
1239 "/Library",
1240 "/Developer/usr/lib"
1241 ],
1242 "bin"=>[
1243 "/Developer/usr/bin"
1244 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001245 },
1246 "beos"=>{
1247 # Haiku has GCC 2.95.3 by default
1248 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001249 "include"=>[
1250 "/boot/common",
1251 "/boot/develop"
1252 ],
1253 "lib"=>[
1254 "/boot/common/lib",
1255 "/boot/system/lib",
1256 "/boot/apps"
1257 ],
1258 "bin"=>[
1259 "/boot/common/bin",
1260 "/boot/system/bin",
1261 "/boot/develop/abi"
1262 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001264);
1265
1266my %Slash_Type=(
1267 "default"=>"/",
1268 "windows"=>"\\"
1269);
1270
1271my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1272
1273# Global Variables
1274my %COMMON_LANGUAGE=(
1275 1 => "C",
1276 2 => "C" );
1277
1278my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001279my $MAX_CPPFILT_FILE_SIZE = 50000;
1280my $CPPFILT_SUPPORT_FILE;
1281
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +03001282my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION, %CLANG_VERSION);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001283
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001284my $STDCXX_TESTING = 0;
1285my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001286my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287
1288my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001289my $CheckUndefined = 0;
1290
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001291my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001292if($TargetComponent_Opt) {
1293 $TargetComponent = lc($TargetComponent_Opt);
1294}
1295else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296{ # default: library
1297 # other components: header, system, ...
1298 $TargetComponent = "library";
1299}
1300
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001301my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001302
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001303my $SystemRoot;
1304
1305my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001306my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307my %LOG_PATH;
1308my %DEBUG_PATH;
1309my %Cache;
1310my %LibInfo;
1311my $COMPILE_ERRORS = 0;
1312my %CompilerOptions;
1313my %CheckedDyLib;
1314my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1315
1316# Constants (#defines)
1317my %Constants;
1318my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001319my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001320
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001321# Extra Info
1322my %SymbolHeader;
1323my %KnownLibs;
1324
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001325# Templates
1326my %TemplateInstance;
1327my %BasicTemplate;
1328my %TemplateArg;
1329my %TemplateDecl;
1330my %TemplateMap;
1331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001332# Types
1333my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001334my %SkipTypes = (
1335 "1"=>{},
1336 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001337my %CheckedTypes;
1338my %TName_Tid;
1339my %EnumMembName_Id;
1340my %NestedNameSpaces = (
1341 "1"=>{},
1342 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001343my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001344my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001345my %ClassVTable;
1346my %ClassVTable_Content;
1347my %VTableClass;
1348my %AllocableClass;
1349my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001350my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351my %Class_SubClasses;
1352my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001353my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001354my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001356my %CheckedTypeInfo;
1357
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001358# Typedefs
1359my %Typedef_BaseName;
1360my %Typedef_Tr;
1361my %Typedef_Eq;
1362my %StdCxxTypedef;
1363my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001364my %MissedBase;
1365my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001366my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001367
1368# Symbols
1369my %SymbolInfo;
1370my %tr_name;
1371my %mangled_name_gcc;
1372my %mangled_name;
1373my %SkipSymbols = (
1374 "1"=>{},
1375 "2"=>{} );
1376my %SkipNameSpaces = (
1377 "1"=>{},
1378 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001379my %AddNameSpaces = (
1380 "1"=>{},
1381 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001382my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001383my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my %SymbolsList_App;
1385my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001386my %Symbol_Library = (
1387 "1"=>{},
1388 "2"=>{} );
1389my %Library_Symbol = (
1390 "1"=>{},
1391 "2"=>{} );
1392my %DepSymbol_Library = (
1393 "1"=>{},
1394 "2"=>{} );
1395my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001396 "1"=>{},
1397 "2"=>{} );
1398my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001399my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001401my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001402my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001403my %Library_Needed= (
1404 "1"=>{},
1405 "2"=>{} );
Andrey Ponomarenko991da682016-09-07 19:09:50 +03001406my $DisabledMSVCUnmangling = undef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001407
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001408# Extra Info
1409my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001410my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001412# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001413my %Include_Preamble = (
1414 "1"=>[],
1415 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001417my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418my %HeaderName_Paths;
1419my %Header_Dependency;
1420my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001421my %Include_Paths = (
1422 "1"=>[],
1423 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424my %INC_PATH_AUTODETECT = (
1425 "1"=>1,
1426 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001427my %Add_Include_Paths = (
1428 "1"=>[],
1429 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001430my %Skip_Include_Paths;
1431my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001432my %Header_ErrorRedirect;
1433my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001434my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001435my %Header_ShouldNotBeUsed;
1436my %RecursiveIncludes;
1437my %Header_Include_Prefix;
1438my %SkipHeaders;
1439my %SkipHeadersList=(
1440 "1"=>{},
1441 "2"=>{} );
1442my %SkipLibs;
1443my %Include_Order;
1444my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001445my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001446my %TUnit_Funcs;
1447my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001448
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001449my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450 "1"=>0,
1451 "2"=>0 );
1452my %AutoPreambleMode = (
1453 "1"=>0,
1454 "2"=>0 );
1455my %MinGWMode = (
1456 "1"=>0,
1457 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001458my %Cpp0xMode = (
1459 "1"=>0,
1460 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461
1462# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001463my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001464my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001465my %RegisteredSONAMEs;
1466my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001468my %CheckedArch;
1469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001470# System Objects
1471my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001472my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001473my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001474
1475# System Headers
1476my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001477my @DefaultCppPaths;
1478my @DefaultGccPaths;
1479my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001480my %DefaultCppHeader;
1481my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001482my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001483
1484# Merging
1485my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001486my $Version;
1487my %AddedInt;
1488my %RemovedInt;
1489my %AddedInt_Virt;
1490my %RemovedInt_Virt;
1491my %VirtualReplacement;
1492my %ChangedTypedef;
1493my %CompatRules;
1494my %IncompleteRules;
1495my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001496my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001497my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001498my %ReturnedClass;
1499my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001500my %SourceAlternative;
1501my %SourceAlternative_B;
1502my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001503my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001504
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001505#Report
1506my %TypeChanges;
1507
1508#Speedup
1509my %TypeProblemsIndex;
1510
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001511# Calling Conventions
1512my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001513 1=>{ "R"=>0, "P"=>0 },
1514 2=>{ "R"=>0, "P"=>0 }
1515);
1516
1517# ABI Dump
1518my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001519
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001520# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001521my %TargetLibs;
1522my %TargetHeaders;
1523
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001524# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my $OStarget = $OSgroup;
1526my %TargetTools;
1527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001528# Recursion locks
1529my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001530my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001531my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001532my @RecurInclude;
1533my @RecurConstant;
1534
1535# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001536my %SystemPaths = (
1537 "include"=>[],
1538 "lib"=>[],
1539 "bin"=>[]
1540);
1541my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001542my $GCC_PATH;
1543
1544# Symbols versioning
1545my %SymVer = (
1546 "1"=>{},
1547 "2"=>{} );
1548
1549# Problem descriptions
1550my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001551my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552my %TotalAffected;
1553
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001554# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001555my $ContentID = 1;
1556my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001557my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1558my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559my $ContentSpanEnd = "</span>\n";
1560my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1561my $ContentDivEnd = "</div>\n";
1562my $Content_Counter = 0;
1563
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001564# Modes
1565my $JoinReport = 1;
1566my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001567
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001568my %Severity_Val=(
1569 "High"=>3,
1570 "Medium"=>2,
1571 "Low"=>1,
1572 "Safe"=>-1
1573);
1574
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001575sub get_Modules()
1576{
1577 my $TOOL_DIR = get_dirname($0);
1578 if(not $TOOL_DIR)
1579 { # patch for MS Windows
1580 $TOOL_DIR = ".";
1581 }
1582 my @SEARCH_DIRS = (
1583 # tool's directory
1584 abs_path($TOOL_DIR),
1585 # relative path to modules
1586 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001587 # install path
1588 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001589 );
1590 foreach my $DIR (@SEARCH_DIRS)
1591 {
1592 if(not is_abs($DIR))
1593 { # relative path
1594 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1595 }
1596 if(-d $DIR."/modules") {
1597 return $DIR."/modules";
1598 }
1599 }
1600 exitStatus("Module_Error", "can't find modules");
1601}
1602
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001603my %LoadedModules = ();
1604
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001605sub loadModule($)
1606{
1607 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001608 if(defined $LoadedModules{$Name}) {
1609 return;
1610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001611 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1612 if(not -f $Path) {
1613 exitStatus("Module_Error", "can't access \'$Path\'");
1614 }
1615 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001616 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001617}
1618
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001619sub readModule($$)
1620{
1621 my ($Module, $Name) = @_;
1622 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1623 if(not -f $Path) {
1624 exitStatus("Module_Error", "can't access \'$Path\'");
1625 }
1626 return readFile($Path);
1627}
1628
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001629sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001630{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001631 my $Number = $_[0];
1632 if(not $Number) {
1633 $Number = 1;
1634 }
1635 else {
1636 $Number = int($Number)+1;
1637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001638 if($Number>3) {
1639 return $Number."th";
1640 }
1641 elsif($Number==1) {
1642 return "1st";
1643 }
1644 elsif($Number==2) {
1645 return "2nd";
1646 }
1647 elsif($Number==3) {
1648 return "3rd";
1649 }
1650 else {
1651 return $Number;
1652 }
1653}
1654
1655sub search_Tools($)
1656{
1657 my $Name = $_[0];
1658 return "" if(not $Name);
1659 if(my @Paths = keys(%TargetTools))
1660 {
1661 foreach my $Path (@Paths)
1662 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001663 if(-f join_P($Path, $Name)) {
1664 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001665 }
1666 if($CrossPrefix)
1667 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001668 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001669 if(-f $Candidate) {
1670 return $Candidate;
1671 }
1672 }
1673 }
1674 }
1675 else {
1676 return "";
1677 }
1678}
1679
1680sub synch_Cmd($)
1681{
1682 my $Name = $_[0];
1683 if(not $GCC_PATH)
1684 { # GCC was not found yet
1685 return "";
1686 }
1687 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001688 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001689 return $Candidate;
1690 }
1691 return "";
1692}
1693
1694sub get_CmdPath($)
1695{
1696 my $Name = $_[0];
1697 return "" if(not $Name);
1698 if(defined $Cache{"get_CmdPath"}{$Name}) {
1699 return $Cache{"get_CmdPath"}{$Name};
1700 }
1701 my %BinUtils = map {$_=>1} (
1702 "c++filt",
1703 "objdump",
1704 "readelf"
1705 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001706 if($BinUtils{$Name} and $GCC_PATH)
1707 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001708 if(my $Dir = get_dirname($GCC_PATH)) {
1709 $TargetTools{$Dir}=1;
1710 }
1711 }
1712 my $Path = search_Tools($Name);
1713 if(not $Path and $OSgroup eq "windows") {
1714 $Path = search_Tools($Name.".exe");
1715 }
1716 if(not $Path and $BinUtils{$Name})
1717 {
1718 if($CrossPrefix)
1719 { # user-defined prefix
1720 $Path = search_Cmd($CrossPrefix."-".$Name);
1721 }
1722 }
1723 if(not $Path and $BinUtils{$Name})
1724 {
1725 if(my $Candidate = synch_Cmd($Name))
1726 { # synch with GCC
1727 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001728 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001729 if(-f $Candidate) {
1730 $Path = $Candidate;
1731 }
1732 }
1733 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001734 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001735 $Path = $Candidate;
1736 }
1737 }
1738 }
1739 if(not $Path) {
1740 $Path = search_Cmd($Name);
1741 }
1742 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001743 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 $Path=search_Cmd($Name.".exe");
1745 }
1746 if($Path=~/\s/) {
1747 $Path = "\"".$Path."\"";
1748 }
1749 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1750}
1751
1752sub search_Cmd($)
1753{
1754 my $Name = $_[0];
1755 return "" if(not $Name);
1756 if(defined $Cache{"search_Cmd"}{$Name}) {
1757 return $Cache{"search_Cmd"}{$Name};
1758 }
1759 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1760 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1761 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001762 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001763 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001764 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001765 if(-f $CmdPath)
1766 {
1767 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001768 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001769 }
1770 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1771 }
1772 }
1773 return ($Cache{"search_Cmd"}{$Name} = "");
1774}
1775
1776sub get_CmdPath_Default($)
1777{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001778 return "" if(not $_[0]);
1779 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1780 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001781 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001782 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1783}
1784
1785sub get_CmdPath_Default_I($)
1786{ # search in PATH
1787 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001788 if($Name=~/find/)
1789 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001790 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001791 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 }
1793 }
1794 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001795 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001797 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001798 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001799 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001800 if($OSgroup eq "windows")
1801 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001802 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001803 return $Name;
1804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001805 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001806 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001807 {
1808 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001809 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001810 }
1811 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001812 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001813}
1814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001815sub classifyPath($)
1816{
1817 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001818 if($Path=~/[\*\+\(\[\|]/)
1819 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001820 return ($Path, "Pattern");
1821 }
1822 elsif($Path=~/[\/\\]/)
1823 { # directory or relative path
1824 return (path_format($Path, $OSgroup), "Path");
1825 }
1826 else {
1827 return ($Path, "Name");
1828 }
1829}
1830
1831sub readDescriptor($$)
1832{
1833 my ($LibVersion, $Content) = @_;
1834 return if(not $LibVersion);
1835 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1836 if(not $Content) {
1837 exitStatus("Error", "$DName is empty");
1838 }
1839 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001840 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001841 }
1842 $Content=~s/\/\*(.|\n)+?\*\///g;
1843 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001844
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001845 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1846 if($TargetVersion{$LibVersion}) {
1847 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1848 }
1849 if(not $Descriptor{$LibVersion}{"Version"}) {
1850 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1851 }
1852 if($Content=~/{RELPATH}/)
1853 {
1854 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1855 $Content =~ s/{RELPATH}/$RelDir/g;
1856 }
1857 else
1858 {
1859 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1860 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1861 }
1862 }
1863
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001864 my $DHeaders = parseTag(\$Content, "headers");
1865 if(not $DHeaders) {
1866 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1867 }
1868 elsif(lc($DHeaders) ne "none")
1869 { # append the descriptor headers list
1870 if($Descriptor{$LibVersion}{"Headers"})
1871 { # multiple descriptors
1872 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001873 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001874 else {
1875 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1876 }
1877 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1878 {
1879 if(not -e $Path) {
1880 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001881 }
1882 }
1883 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001884
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 if(not $CheckHeadersOnly_Opt)
1886 {
1887 my $DObjects = parseTag(\$Content, "libs");
1888 if(not $DObjects) {
1889 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1890 }
1891 elsif(lc($DObjects) ne "none")
1892 { # append the descriptor libraries list
1893 if($Descriptor{$LibVersion}{"Libs"})
1894 { # multiple descriptors
1895 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1896 }
1897 else {
1898 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1899 }
1900 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1901 {
1902 if(not -e $Path) {
1903 exitStatus("Access_Error", "can't access \'$Path\'");
1904 }
1905 }
1906 }
1907 }
1908 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1909 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001910 if(not -d $Path) {
1911 exitStatus("Access_Error", "can't access directory \'$Path\'");
1912 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001913 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001915 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
1917 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1918 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 if(not -d $Path) {
1920 exitStatus("Access_Error", "can't access directory \'$Path\'");
1921 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001922 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001924 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001925 }
1926 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1927 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001928 if(not -d $Path) {
1929 exitStatus("Access_Error", "can't access directory \'$Path\'");
1930 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001931 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001933 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001934 $TargetTools{$Path}=1;
1935 }
1936 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1937 $CrossPrefix = $Prefix;
1938 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001939 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001940 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1941 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001942 if(not -d $Path) {
1943 exitStatus("Access_Error", "can't access directory \'$Path\'");
1944 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001945 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001946 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001947 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001948 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001949 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001950 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1951 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 if(not -d $Path) {
1953 exitStatus("Access_Error", "can't access directory \'$Path\'");
1954 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001955 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001956 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001957 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001958 }
1959 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001960 { # skip some auto-generated include paths
1961 if(not is_abs($Path))
1962 {
1963 if(my $P = abs_path($Path)) {
1964 $Path = $P;
1965 }
1966 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001967 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001968 }
1969 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001970 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001971 my ($CPath, $Type) = classifyPath($Path);
1972 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001973 }
1974 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001975 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1976 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001977 if($Option!~/\A\-(Wl|l|L)/)
1978 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001979 $CompilerOptions{$LibVersion} .= " ".$Option;
1980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001981 }
1982 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1983 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1984 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001985 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001987 my ($CPath, $Type) = classifyPath($Path);
1988 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001989 }
1990 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1991 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1992 {
1993 my ($CPath, $Type) = classifyPath($Path);
1994 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1995 }
1996 if(my $DDefines = parseTag(\$Content, "defines"))
1997 {
1998 if($Descriptor{$LibVersion}{"Defines"})
1999 { # multiple descriptors
2000 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2001 }
2002 else {
2003 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2004 }
2005 }
2006 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2007 {
2008 if($Order=~/\A(.+):(.+)\Z/) {
2009 $Include_Order{$LibVersion}{$1} = $2;
2010 }
2011 }
2012 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2013 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002014 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002015 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2016 }
2017 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2018 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002019 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002020 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2021 }
2022 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2023 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2024 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002025 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2026 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002028 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2029 $SkipConstants{$LibVersion}{$Constant} = 1;
2030 }
2031 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2032 {
2033 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002034 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2036 }
2037 else {
2038 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2039 }
2040 }
2041}
2042
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002043sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002045 my $CodeRef = shift(@_);
2046 my $Tag = shift(@_);
2047 if(not $Tag or not $CodeRef) {
2048 return undef;
2049 }
2050 my $Sp = 0;
2051 if(@_) {
2052 $Sp = shift(@_);
2053 }
2054 my $Start = index(${$CodeRef}, "<$Tag>");
2055 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002056 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002057 my $End = index(${$CodeRef}, "</$Tag>");
2058 if($End!=-1)
2059 {
2060 my $TS = length($Tag)+3;
2061 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2062 substr($Content, 0, $TS-1, ""); # cut start tag
2063 substr($Content, -$TS, $TS, ""); # cut end tag
2064 if(not $Sp)
2065 {
2066 $Content=~s/\A\s+//g;
2067 $Content=~s/\s+\Z//g;
2068 }
2069 if(substr($Content, 0, 1) ne "<") {
2070 $Content = xmlSpecChars_R($Content);
2071 }
2072 return $Content;
2073 }
2074 }
2075 return undef;
2076}
2077
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002078sub getInfo($)
2079{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002080 my $DumpPath = $_[0];
2081 return if(not $DumpPath or not -f $DumpPath);
2082
2083 readTUDump($DumpPath);
2084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002085 # processing info
2086 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002087
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002088 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002089 setAnonTypedef_All();
2090 }
2091
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002092 getTypeInfo_All();
2093 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002094 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002095 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002096 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002097
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002098 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002099 %LibInfo = ();
2100 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002101 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002102 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002103 %TemplateDecl = ();
2104 %StdCxxTypedef = ();
2105 %MissedTypedef = ();
2106 %Typedef_Tr = ();
2107 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002108 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002109
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002110 # clean cache
2111 delete($Cache{"getTypeAttr"});
2112 delete($Cache{"getTypeDeclId"});
2113
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002114 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002115 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002116 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002117 }
2118 else
2119 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002120 if($BinaryOnly and not $ExtendedCheck)
2121 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002122 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002123 }
2124 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002125 remove_Unused($Version, "Extended");
2126 }
2127 }
2128
2129 if($CheckInfo)
2130 {
2131 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2132 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2133 }
2134
2135 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2136 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002138 }
2139
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002140 if($Debug) {
2141 # debugMangling($Version);
2142 }
2143}
2144
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002145sub readTUDump($)
2146{
2147 my $DumpPath = $_[0];
2148
2149 open(TU_DUMP, $DumpPath);
2150 local $/ = undef;
2151 my $Content = <TU_DUMP>;
2152 close(TU_DUMP);
2153
2154 unlink($DumpPath);
2155
2156 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002157 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002158
2159 # clean memory
2160 undef $Content;
2161
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002162 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002163
2164 foreach (0 .. $#Lines)
2165 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002166 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002167 { # get a number and attributes of a node
2168 next if(not $NodeType{$2});
2169 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002170 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002171 }
2172
2173 # clean memory
2174 delete($Lines[$_]);
2175 }
2176
2177 # clean memory
2178 undef @Lines;
2179}
2180
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002181sub simplifyConstants()
2182{
2183 foreach my $Constant (keys(%{$Constants{$Version}}))
2184 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002185 if(defined $Constants{$Version}{$Constant}{"Header"})
2186 {
2187 my $Value = $Constants{$Version}{$Constant}{"Value"};
2188 if(defined $EnumConstants{$Version}{$Value}) {
2189 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2190 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002191 }
2192 }
2193}
2194
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002195sub simplifyNames()
2196{
2197 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2198 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002199 if($Typedef_Eq{$Version}{$Base}) {
2200 next;
2201 }
2202 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2203 if($#Translations==0)
2204 {
2205 if(length($Translations[0])<=length($Base)) {
2206 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2207 }
2208 }
2209 else
2210 { # select most appropriate
2211 foreach my $Tr (@Translations)
2212 {
2213 if($Base=~/\A\Q$Tr\E/)
2214 {
2215 $Typedef_Eq{$Version}{$Base} = $Tr;
2216 last;
2217 }
2218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002219 }
2220 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002221 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002222 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002223 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002224 if(not $TypeName) {
2225 next;
2226 }
2227 next if(index($TypeName,"<")==-1);# template instances only
2228 if($TypeName=~/>(::\w+)+\Z/)
2229 { # skip unused types
2230 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002232 foreach my $Base (sort {length($b)<=>length($a)}
2233 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002234 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002235 next if(not $Base);
2236 next if(index($TypeName,$Base)==-1);
2237 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002238 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002239 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002240 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2241 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2242 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002243 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002244 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2245 {
2246 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2247 {
2248 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2249 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002250 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002251 }
2252 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002255 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002256 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002257 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2258 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002259 }
2260}
2261
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002262sub setAnonTypedef_All()
2263{
2264 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2265 {
2266 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2267 {
2268 if(isAnon(getNameByInfo($InfoId))) {
2269 $TypedefToAnon{getTypeId($InfoId)} = 1;
2270 }
2271 }
2272 }
2273}
2274
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002275sub setTemplateParams_All()
2276{
2277 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2278 {
2279 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2280 setTemplateParams($_);
2281 }
2282 }
2283}
2284
2285sub setTemplateParams($)
2286{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002287 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002288 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002289 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002290 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002292 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002293 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002294 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002295 setTemplateInstParams($_[0], $TmplInst_Id);
2296 }
2297 }
2298
2299 $BasicTemplate{$Version}{$Tid} = $_[0];
2300
2301 if(my $Prms = getTreeAttr_Prms($_[0]))
2302 {
2303 if(my $Valu = getTreeAttr_Valu($Prms))
2304 {
2305 my $Vector = getTreeVec($Valu);
2306 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2307 {
2308 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2309 {
2310 if(my $Name = getNameByInfo($Val))
2311 {
2312 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2313 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2314 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2315 }
2316 else {
2317 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2318 }
2319 }
2320 }
2321 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002323 }
2324 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002325 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002326 {
2327 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2328 {
2329 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002330 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002331 }
2332 }
2333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002334}
2335
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002336sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002337{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002338 my ($Tmpl, $Inst) = @_;
2339
2340 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002342 my ($Params_InfoId, $ElemId) = ();
2343 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2344 $Params_InfoId = $1;
2345 }
2346 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2347 $ElemId = $1;
2348 }
2349 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002350 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002351 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2352 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2353 {
2354 my ($PPos, $PTypeId) = ($1, $2);
2355 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2356 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002357 if($PType eq "template_type_parm") {
2358 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002359 }
2360 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002361 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2362 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002363 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002364 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002365 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002366 else
2367 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002368 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002369 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002371 }
2372 }
2373 }
2374}
2375
2376sub getTypeDeclId($)
2377{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002378 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002379 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002380 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2381 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2382 }
2383 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2384 {
2385 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2386 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2387 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002389 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002390 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002391}
2392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393sub getTypeInfo_All()
2394{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002395 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002396 { # support for GCC < 4.5
2397 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2398 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2399 # FIXME: check GCC versions
2400 addMissedTypes_Pre();
2401 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002402
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002403 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002404 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002405 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2406 if($IType=~/_type\Z/ and $IType ne "function_type"
2407 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002408 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002409 }
2410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002411
2412 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002413 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002414 "Name" => "...",
2415 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002416 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002417 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002418 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002419
2420 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002421 { # support for GCC < 4.5
2422 addMissedTypes_Post();
2423 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002424
2425 if($ADD_TMPL_INSTANCES)
2426 {
2427 # templates
2428 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2429 {
2430 if(defined $TemplateMap{$Version}{$Tid}
2431 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2432 {
2433 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2434 {
2435 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2436 {
2437 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2438 {
2439 if(my %MAttr = getTypeAttr($MembTypeId))
2440 {
2441 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2442 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2443 }
2444 }
2445 }
2446 }
2447 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2448 {
2449 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2450 {
2451 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2452
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002453 if($NBid ne $Bid
2454 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002455 {
2456 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2457 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2458 }
2459 }
2460 }
2461 }
2462 }
2463 }
2464}
2465
2466sub createType($$)
2467{
2468 my ($Attr, $LibVersion) = @_;
2469 my $NewId = ++$MAX_ID;
2470
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002471 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002472 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002473 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002474
2475 return "$NewId";
2476}
2477
2478sub instType($$$)
2479{ # create template instances
2480 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002481
2482 if(not $TypeInfo{$LibVersion}{$Tid}) {
2483 return undef;
2484 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002485 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2486
2487 foreach my $Key (sort keys(%{$Map}))
2488 {
2489 if(my $Val = $Map->{$Key})
2490 {
2491 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2492
2493 if(defined $Attr->{"NameSpace"}) {
2494 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2495 }
2496 foreach (keys(%{$Attr->{"TParam"}})) {
2497 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2498 }
2499 }
2500 else
2501 { # remove absent
2502 # _Traits, etc.
2503 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002504 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002505 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2506 }
2507 foreach (keys(%{$Attr->{"TParam"}}))
2508 {
2509 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2510 delete($Attr->{"TParam"}{$_});
2511 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002512 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002513 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2514 }
2515 }
2516 }
2517 }
2518
2519 my $Tmpl = 0;
2520
2521 if(defined $Attr->{"TParam"})
2522 {
2523 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2524 {
2525 my $PName = $Attr->{"TParam"}{$_}{"name"};
2526
2527 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2528 {
2529 my %Base = get_BaseType($PTid, $LibVersion);
2530
2531 if($Base{"Type"} eq "TemplateParam"
2532 or defined $Base{"Template"})
2533 {
2534 $Tmpl = 1;
2535 last
2536 }
2537 }
2538 }
2539 }
2540
2541 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2542 return "$Id";
2543 }
2544 else
2545 {
2546 if(not $Tmpl) {
2547 delete($Attr->{"Template"});
2548 }
2549
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002550 my $New = createType($Attr, $LibVersion);
2551
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002552 my %EMap = ();
2553 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2554 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2555 }
2556 foreach (keys(%{$Map})) {
2557 $EMap{$_} = $Map->{$_};
2558 }
2559
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002560 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2561 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002562 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002563 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002564 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002565 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002566 {
2567 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2568
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002569 if($NBid ne $Bid
2570 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002571 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002572 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2573 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002574 }
2575 }
2576 }
2577
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002578 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002579 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002580 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2581 {
2582 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2583 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2584 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002585 }
2586 }
2587
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002588 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002590 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2591 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002592 }
2593 }
2594
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002595 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2596 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002597 }
2598
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002599 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002601}
2602
2603sub addMissedTypes_Pre()
2604{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002605 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2607 { # detecting missed typedefs
2608 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2609 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002610 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002612 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002613 if($TypeType eq "Unknown")
2614 { # template_type_parm
2615 next;
2616 }
2617 my $TypeDeclId = getTypeDeclId($TypeId);
2618 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2619 my $TypedefName = getNameByInfo($MissedTDid);
2620 next if(not $TypedefName);
2621 next if($TypedefName eq "__float80");
2622 next if(isAnon($TypedefName));
2623 if(not $TypeDeclId
2624 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002625 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 }
2627 }
2628 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002629 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002630 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002632 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002633 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002634 next;
2635 }
2636 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002638 if(not $TypedefName) {
2639 next;
2640 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002641 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002642 my %MissedInfo = ( # typedef info
2643 "Name" => $TypedefName,
2644 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002645 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002647 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002648 my ($H, $L) = getLocation($MissedTDid);
2649 $MissedInfo{"Header"} = $H;
2650 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002651 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 { # other types
2653 next;
2654 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002657 next;
2658 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002659 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002661 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002663 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002665 next;
2666 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002667 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 next;
2669 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002670 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002671 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 next;
2673 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002674 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676 next;
2677 }
2678 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002679
2680 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2681
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002682 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002684 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002685 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002687
2688 # add missed & remove other
2689 $TypeInfo{$Version} = \%AddTypes;
2690 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002691}
2692
2693sub addMissedTypes_Post()
2694{
2695 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2696 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002697 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2698 {
2699 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2700 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2701 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2702 }
2703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002704 }
2705}
2706
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002707sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002709 my $TypeId = $_[0];
2710 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2711 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002713 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002715}
2716
2717sub getArraySize($$)
2718{
2719 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002720 if(my $Size = getSize($TypeId))
2721 {
2722 my $Elems = $Size/$BYTE_SIZE;
2723 while($BaseName=~s/\s*\[(\d+)\]//) {
2724 $Elems/=$1;
2725 }
2726 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2727 {
2728 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2729 $Elems/=$BasicSize;
2730 }
2731 }
2732 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002733 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002734 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002735}
2736
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002737sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002738{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002739 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2742 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002743 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002744 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2745 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2746 if(not $NodeType)
2747 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002748 return ();
2749 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002750 if($NodeType eq "tree_vec")
2751 {
2752 if($Pos!=$#Positions)
2753 { # select last vector of parameters ( ns<P1>::type<P2> )
2754 next;
2755 }
2756 }
2757 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2758 foreach my $P (@Params)
2759 {
2760 if($P eq "") {
2761 return ();
2762 }
2763 elsif($P ne "\@skip\@") {
2764 @TmplParams = (@TmplParams, $P);
2765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002766 }
2767 }
2768 return @TmplParams;
2769}
2770
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002771sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002772{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002773 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002774 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775 if(defined $TypeInfo{$Version}{$TypeId}
2776 and $TypeInfo{$Version}{$TypeId}{"Name"})
2777 { # already created
2778 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002780 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2781 { # incomplete type
2782 return ();
2783 }
2784 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2785
2786 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002787 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002788
2789 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2790 {
2791 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2792 {
2793 if($Info=~/qual[ ]*:/)
2794 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002795 my $NewId = ++$MAX_ID;
2796
2797 $MissedBase{$Version}{$TypeId} = "$NewId";
2798 $MissedBase_R{$Version}{$NewId} = $TypeId;
2799 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2800 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002801 }
2802 }
2803 $TypeAttr{"Type"} = "Typedef";
2804 }
2805 else {
2806 $TypeAttr{"Type"} = getTypeType($TypeId);
2807 }
2808
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002809 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2810 {
2811 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2812 { # local code
2813 return ();
2814 }
2815 }
2816
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 if($TypeAttr{"Type"} eq "Unknown") {
2818 return ();
2819 }
2820 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2821 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002822 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 if(my $TName = $TypeAttr{"Name"})
2824 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002825 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002826 $TName_Tid{$Version}{$TName} = $TypeId;
2827 return %TypeAttr;
2828 }
2829 else {
2830 return ();
2831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002832 }
2833 elsif($TypeAttr{"Type"} eq "Array")
2834 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002835 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2836 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002837 return ();
2838 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002839 if(my $Algn = getAlgn($TypeId)) {
2840 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2841 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002842 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002843 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002844 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002845 if(not $BTAttr{"Name"}) {
2846 return ();
2847 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002848 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002849 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002850 if(my $Size = getSize($TypeId)) {
2851 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2852 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002853 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002854 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2855 }
2856 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002857 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002859 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002860 else
2861 {
2862 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002863 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002864 $TypeAttr{"Name"} = $1."[]".$2;
2865 }
2866 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002867 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002869 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002870 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002871 if($BTAttr{"Header"}) {
2872 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002873 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002874 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002875 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2876 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002877 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002878 return ();
2879 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002880 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002881 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002883 if($TypeAttr{"Name"})
2884 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002885 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002886
2887 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2888 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002889 { # NOTE: register only one int: with built-in decl
2890 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2891 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2892 }
2893 }
2894 return %TypeAttr;
2895 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002896 else {
2897 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002899 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002900 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2901 {
2902 %TypeAttr = getTrivialTypeAttr($TypeId);
2903 if($TypeAttr{"Name"})
2904 {
2905 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2906 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2907 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2908 }
2909 return %TypeAttr;
2910 }
2911 else {
2912 return ();
2913 }
2914 }
2915 elsif($TypeAttr{"Type"} eq "SizeOf")
2916 {
2917 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2918 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2919 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2920 if($TypeAttr{"Name"})
2921 {
2922 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2923 return %TypeAttr;
2924 }
2925 else {
2926 return ();
2927 }
2928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002929 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002930 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002931 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2932 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002933 return ();
2934 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002935 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002936 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002937 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002938 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002939 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002940 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002941 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002943 }
2944 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002945 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002946 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002947 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002948 return ();
2949 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002951 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002952 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002953 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002954 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002955 }
2956 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002957 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002958 {
2959 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002961 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002963 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2964 }
2965 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002966 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002967 }
2968 }
2969 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002971 }
2972 if($TypeAttr{"Type"} eq "Typedef")
2973 {
2974 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002975
2976 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2977 return ();
2978 }
2979
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002980 if(isAnon($TypeAttr{"Name"}))
2981 { # anon typedef to anon type: ._N
2982 return ();
2983 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002984
2985 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2986 { # artificial typedef of "struct X" to "X"
2987 $TypeAttr{"Artificial"} = 1;
2988 }
2989
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002990 if(my $NS = getNameSpace($TypeDeclId))
2991 {
2992 my $TypeName = $TypeAttr{"Name"};
2993 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2994 { # "some_type" is the typedef to "struct some_type" in C++
2995 if($3) {
2996 $TypeAttr{"Name"} = $3."::".$TypeName;
2997 }
2998 }
2999 else
3000 {
3001 $TypeAttr{"NameSpace"} = $NS;
3002 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003003
3004 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3005 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3006 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003007 if($BTAttr{"NameSpace"}
3008 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003009 { # types like "std::fpos<__mbstate_t>" are
3010 # not covered by typedefs in the TU dump
3011 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003012 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3013 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003014 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003015 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003016 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003017 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003018 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003019 }
3020 }
3021 }
3022 }
3023 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003024 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003025 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003026 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003027 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3028 { # typedef int*const TYPEDEF; // first
3029 # int foo(TYPEDEF p); // const is optimized out
3030 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3031 if($BTAttr{"Name"}=~/</)
3032 {
3033 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3034 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003036 }
3037 }
3038 }
3039 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3040 }
3041 if(not $TypeAttr{"Size"})
3042 {
3043 if($TypeAttr{"Type"} eq "Pointer") {
3044 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3045 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003046 elsif($BTAttr{"Size"}) {
3047 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003048 }
3049 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003050 if(my $Algn = getAlgn($TypeId)) {
3051 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3052 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003053 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003054 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3055 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003056 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003057 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003058 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003059 { # typedef to "class Class"
3060 # should not be registered in TName_Tid
3061 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3062 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 }
3065 return %TypeAttr;
3066 }
3067}
3068
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003069sub getTreeVec($)
3070{
3071 my %Vector = ();
3072 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3073 {
3074 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3075 { # string length is N-1 because of the null terminator
3076 $Vector{$1} = $2;
3077 }
3078 }
3079 return \%Vector;
3080}
3081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003082sub get_TemplateParam($$)
3083{
3084 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003085 return () if(not $Type_Id);
3086 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3087 return () if(not $NodeType);
3088 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003089 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003090 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003091 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 my $Num = getNodeIntCst($Type_Id);
3093 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003095 }
3096 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003097 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003098 }
3099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003100 elsif($NodeType eq "string_cst") {
3101 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003103 elsif($NodeType eq "tree_vec")
3104 {
3105 my $Vector = getTreeVec($Type_Id);
3106 my @Params = ();
3107 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3108 {
3109 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3110 push(@Params, $P2);
3111 }
3112 }
3113 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003114 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003115 elsif($NodeType eq "parm_decl")
3116 {
3117 (getNameByInfo($Type_Id));
3118 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119 else
3120 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003121 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003122 my $PName = $ParamAttr{"Name"};
3123 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003124 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003125 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003126 if($PName=~/\>/)
3127 {
3128 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003129 $PName = $Cover;
3130 }
3131 }
3132 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003133 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003134 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3135 # template<typename _Key, typename _Compare = std::less<_Key>
3136 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3137 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3138 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3139 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003140 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003142 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003143 }
3144}
3145
3146sub cover_stdcxx_typedef($)
3147{
3148 my $TypeName = $_[0];
3149 if(my @Covers = sort {length($a)<=>length($b)}
3150 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3151 { # take the shortest typedef
3152 # FIXME: there may be more than
3153 # one typedefs to the same type
3154 return $Covers[0];
3155 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003156 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003157 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3158 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3159 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003160 if(my $Cover = $Covers[0])
3161 {
3162 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3163 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003165 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003166 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167}
3168
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169sub getNodeIntCst($)
3170{
3171 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003172 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173 if($EnumMembName_Id{$Version}{$CstId}) {
3174 return $EnumMembName_Id{$Version}{$CstId};
3175 }
3176 elsif((my $Value = getTreeValue($CstId)) ne "")
3177 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003178 if($Value eq "0")
3179 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003180 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003181 return "false";
3182 }
3183 else {
3184 return "0";
3185 }
3186 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003187 elsif($Value eq "1")
3188 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003189 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003190 return "true";
3191 }
3192 else {
3193 return "1";
3194 }
3195 }
3196 else {
3197 return $Value;
3198 }
3199 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003200 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003201}
3202
3203sub getNodeStrCst($)
3204{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003205 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3206 {
3207 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003208 {
3209 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3210 { # string length is N-1 because of the null terminator
3211 return substr($1, 0, $2-1);
3212 }
3213 else
3214 { # identifier_node
3215 return substr($1, 0, $2);
3216 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003218 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003219 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003220}
3221
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003222sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003223{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003224 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003225 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3226 if($Type eq "FieldPtr") {
3227 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3228 }
3229 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3230 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003231 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003232 if($Type eq "MethodPtr")
3233 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003234 if(my $Size = getSize($TypeId))
3235 {
3236 $Size/=$BYTE_SIZE;
3237 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003239 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003240 if(my $Algn = getAlgn($TypeId)) {
3241 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003243 # Return
3244 if($Type eq "FieldPtr")
3245 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003246 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003247 if($ReturnAttr{"Name"}) {
3248 $MemPtrName .= $ReturnAttr{"Name"};
3249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003250 $TypeAttr{"Return"} = $PtrId;
3251 }
3252 else
3253 {
3254 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3255 {
3256 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003257 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3258 if(not $ReturnAttr{"Name"})
3259 { # templates
3260 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003262 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003263 $TypeAttr{"Return"} = $ReturnTypeId;
3264 }
3265 }
3266 # Class
3267 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3268 {
3269 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003270 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003271 if($Class{"Name"}) {
3272 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3273 }
3274 else {
3275 $MemPtrName .= " (*)";
3276 }
3277 }
3278 else {
3279 $MemPtrName .= " (*)";
3280 }
3281 # Parameters
3282 if($Type eq "FuncPtr"
3283 or $Type eq "MethodPtr")
3284 {
3285 my @ParamTypeName = ();
3286 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3287 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003288 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003289 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003290 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003291 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003292 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3293 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003295 my $PTypeId = $1;
3296 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003297 if(not $ParamAttr{"Name"})
3298 { # templates (template_type_parm), etc.
3299 return ();
3300 }
3301 if($ParamAttr{"Name"} eq "void") {
3302 last;
3303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003304 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003305 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003306 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003307 push(@ParamTypeName, $ParamAttr{"Name"});
3308 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003309 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3310 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003311 }
3312 else {
3313 last;
3314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003315 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003316 else {
3317 last;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 }
3320 }
3321 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3322 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003323 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003324 return %TypeAttr;
3325}
3326
3327sub getTreeTypeName($)
3328{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003329 my $TypeId = $_[0];
3330 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003331 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003332 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003333 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003334 if(my $Name = getNameByInfo($TypeId))
3335 { # bit_size_type
3336 return $Name;
3337 }
3338 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003339 return "unsigned int";
3340 }
3341 else {
3342 return "int";
3343 }
3344 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003345 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003346 return getNameByInfo($1);
3347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003348 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003349 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003350}
3351
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003352sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003353{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003354 my $Ptd = pointTo($_[0]);
3355 return 0 if(not $Ptd);
3356 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003358 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3359 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003360 }
3361 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003362 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3363 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003364 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003365 if($InfoT1 eq "pointer_type"
3366 and $InfoT2 eq "function_type") {
3367 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003368 }
3369 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003370 return 0;
3371}
3372
3373sub isMethodPtr($)
3374{
3375 my $Ptd = pointTo($_[0]);
3376 return 0 if(not $Ptd);
3377 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3378 {
3379 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3380 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3381 and $Info=~/ ptrmem /) {
3382 return 1;
3383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003384 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003385 return 0;
3386}
3387
3388sub isFieldPtr($)
3389{
3390 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3391 {
3392 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3393 and $Info=~/ ptrmem /) {
3394 return 1;
3395 }
3396 }
3397 return 0;
3398}
3399
3400sub pointTo($)
3401{
3402 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3403 {
3404 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3405 return $1;
3406 }
3407 }
3408 return "";
3409}
3410
3411sub getTypeTypeByTypeId($)
3412{
3413 my $TypeId = $_[0];
3414 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3415 {
3416 my $NType = $NodeType{$TType};
3417 if($NType eq "Intrinsic") {
3418 return $NType;
3419 }
3420 elsif(isFuncPtr($TypeId)) {
3421 return "FuncPtr";
3422 }
3423 elsif(isMethodPtr($TypeId)) {
3424 return "MethodPtr";
3425 }
3426 elsif(isFieldPtr($TypeId)) {
3427 return "FieldPtr";
3428 }
3429 elsif($NType ne "Other") {
3430 return $NType;
3431 }
3432 }
3433 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003434}
3435
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003436my %UnQual = (
3437 "r"=>"restrict",
3438 "v"=>"volatile",
3439 "c"=>"const",
3440 "cv"=>"const volatile"
3441);
3442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003443sub getQual($)
3444{
3445 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003446 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3447 {
3448 my ($Qual, $To) = ();
3449 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3450 $Qual = $UnQual{$1};
3451 }
3452 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3453 $To = $1;
3454 }
3455 if($Qual and $To) {
3456 return ($Qual, $To);
3457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003458 }
3459 return ();
3460}
3461
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003462sub getQualType($)
3463{
3464 if($_[0] eq "const volatile") {
3465 return "ConstVolatile";
3466 }
3467 return ucfirst($_[0]);
3468}
3469
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003471{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003472 my $TypeId = $_[0];
3473 my $TypeDeclId = getTypeDeclId($TypeId);
3474 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003475 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003476 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3477 return "Typedef";
3478 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003479 }
3480 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3481 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003482 if(($Qual or $To) and $TypeDeclId
3483 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003484 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003485 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003487 elsif(not $MissedBase_R{$Version}{$TypeId}
3488 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003489 return "Typedef";
3490 }
3491 elsif($Qual)
3492 { # qualified types
3493 return getQualType($Qual);
3494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003495
3496 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3497 { # typedef struct { ... } name
3498 $TypeTypedef{$Version}{$TypeId} = $1;
3499 }
3500
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003501 my $TypeType = getTypeTypeByTypeId($TypeId);
3502 if($TypeType eq "Struct")
3503 {
3504 if($TypeDeclId
3505 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3506 return "Template";
3507 }
3508 }
3509 return $TypeType;
3510}
3511
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003512sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003513{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003514 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003516 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3517 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3518 return 0;
3519 }
3520 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3521 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003522 if(my $TDid = getTypeDeclId($_[0]))
3523 {
3524 if(getTypeId($TDid) eq $_[0]
3525 and getNameByInfo($TDid))
3526 {
3527 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3528 return $1;
3529 }
3530 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003531 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003532 }
3533 }
3534 return 0;
3535}
3536
3537sub selectBaseType($)
3538{
3539 my $TypeId = $_[0];
3540 if(defined $MissedTypedef{$Version}{$TypeId})
3541 { # add missed typedefs
3542 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3543 return ($TypeId, "");
3544 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003546 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3547 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548
3549 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3550 my $MB = $MissedBase{$Version}{$TypeId};
3551
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003552 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003553 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003554 and (getTypeId($1) ne $TypeId)
3555 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003556 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003557 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003558 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003559 elsif($MB)
3560 { # add base
3561 return ($MB, "");
3562 }
3563 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003564 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003565 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003566 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003567 elsif($Qual or $To)
3568 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003569 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003571 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003572 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003573 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003574 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003576 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003577 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003578 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003579 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003580 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003583 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003584 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003585 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003586 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003589
3590 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003591}
3592
3593sub getSymbolInfo_All()
3594{
3595 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3596 { # reverse order
3597 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003598 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003599 }
3600 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003601
3602 if($ADD_TMPL_INSTANCES)
3603 {
3604 # templates
3605 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3606 {
3607 my %Map = ();
3608
3609 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3610 {
3611 if(defined $TemplateMap{$Version}{$ClassId})
3612 {
3613 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3614 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3615 }
3616 }
3617 }
3618
3619 if(defined $TemplateMap{$Version}{$Sid})
3620 {
3621 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3622 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3623 }
3624 }
3625
3626 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3627 {
3628 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3629 {
3630 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3631 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3632 }
3633 }
3634 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3635 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3636 }
3637 }
3638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003639}
3640
3641sub getVarInfo_All()
3642{
3643 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3644 { # reverse order
3645 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003646 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003647 }
3648 }
3649}
3650
3651sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003652 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003653}
3654
3655sub getVarInfo($)
3656{
3657 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003658 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003659 {
3660 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3661 if($NSInfoType and $NSInfoType eq "function_decl") {
3662 return;
3663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003664 }
3665 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3666 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3667 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3668 delete($SymbolInfo{$Version}{$InfoId});
3669 return;
3670 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003671 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003672 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 delete($SymbolInfo{$Version}{$InfoId});
3674 return;
3675 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003676 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3677 delete($SymbolInfo{$Version}{$InfoId});
3678 return;
3679 }
3680 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003681 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3682 {
3683 if($OSgroup eq "windows")
3684 { # cut the offset
3685 $MnglName=~s/\@\d+\Z//g;
3686 }
3687 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003690 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 { # validate mangled name
3692 delete($SymbolInfo{$Version}{$InfoId});
3693 return;
3694 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003695 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003696 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003697 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003698 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003699 }
3700 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3701 { # non-public global data
3702 delete($SymbolInfo{$Version}{$InfoId});
3703 return;
3704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003705 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003706 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003707 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003708 if(not defined $TypeInfo{$Version}{$Rid}
3709 or not $TypeInfo{$Version}{$Rid}{"Name"})
3710 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003711 delete($SymbolInfo{$Version}{$InfoId});
3712 return;
3713 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003714 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3715 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003716 if(defined $Val) {
3717 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003719 }
3720 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003721 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3722 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003723 if(not defined $TypeInfo{$Version}{$ClassId}
3724 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3725 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003726 delete($SymbolInfo{$Version}{$InfoId});
3727 return;
3728 }
3729 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003730 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3731 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003732 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003733 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003734 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003735 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003737 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003738 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003739 if(not $CheckHeadersOnly)
3740 {
3741 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3742 {
3743 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3744 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3745 {
3746 if(link_symbol($ShortName, $Version, "-Deps"))
3747 { # "const" global data is mangled as _ZL... in the TU dump
3748 # but not mangled when compiling a C shared library
3749 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3750 }
3751 }
3752 }
3753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003754 if($COMMON_LANGUAGE{$Version} eq "C++")
3755 {
3756 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3757 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003758 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003759 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3760 }
3761 }
3762 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3763 { # try to mangle symbol (link with libraries)
3764 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3765 }
3766 if($OStarget eq "windows")
3767 {
3768 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3769 { # link MS C++ symbols from library with GCC symbols from headers
3770 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3771 }
3772 }
3773 }
3774 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3775 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3776 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003777 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3778 {
3779 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3780 { # non-target symbols
3781 delete($SymbolInfo{$Version}{$InfoId});
3782 return;
3783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003784 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003785 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3786 {
3787 if(defined $MissedTypedef{$Version}{$Rid})
3788 {
3789 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3790 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3791 }
3792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003793 }
3794 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003795 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003796 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3797 }
3798 if($ShortName=~/\A(_Z|\?)/) {
3799 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3800 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003801
3802 if($ExtraDump) {
3803 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003805}
3806
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003807sub isConstType($$)
3808{
3809 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003810 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003811 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003812 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003813 }
3814 return ($Base{"Type"} eq "Const");
3815}
3816
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817sub getTrivialName($$)
3818{
3819 my ($TypeInfoId, $TypeId) = @_;
3820 my %TypeAttr = ();
3821 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3822 if(not $TypeAttr{"Name"}) {
3823 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3824 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003825 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003826 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003827 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003828 if(isAnon($TypeAttr{"Name"}))
3829 {
3830 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003831 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003832 { # searching for a first not anon scope
3833 if($NSId eq $NameSpaceId) {
3834 last;
3835 }
3836 else
3837 {
3838 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3839 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003840 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003841 last;
3842 }
3843 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003844 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003845 }
3846 }
3847 else
3848 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003849 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003850 {
3851 if($NameSpaceId ne $TypeId) {
3852 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003854 }
3855 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003856 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003857 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3858 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003859 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003860 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003861 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003862 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003863 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003864 if($TypeAttr{"NameSpace"}) {
3865 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003867 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003868 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3869 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003870 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003871 if(my @TParams = getTParams($TypeId, "Type")) {
3872 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3873 }
3874 else {
3875 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003877 }
3878 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3879}
3880
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003881sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003882{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003883 my $TypeId = $_[0];
3884 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003885
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003886 my %TypeAttr = ();
3887
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003888 if($TemplateDecl{$Version}{$TypeId})
3889 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003890 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003891 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003892
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003893 setTypeAccess($TypeId, \%TypeAttr);
3894 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3895 if(isBuiltIn($TypeAttr{"Header"}))
3896 {
3897 delete($TypeAttr{"Header"});
3898 delete($TypeAttr{"Line"});
3899 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003900
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003901 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003902 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3903 if(not $TypeAttr{"Name"}) {
3904 return ();
3905 }
3906 if(not $TypeAttr{"NameSpace"}) {
3907 delete($TypeAttr{"NameSpace"});
3908 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003909
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003910 if($TypeAttr{"Type"} eq "Intrinsic")
3911 {
3912 if(defined $TypeAttr{"Header"})
3913 {
3914 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3915 { # support for SUSE 11.2
3916 # integer_type has srcp dump{1-2}.i
3917 delete($TypeAttr{"Header"});
3918 }
3919 }
3920 }
3921
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003922 my $Tmpl = undef;
3923
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003924 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003925 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3927
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003928 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003929 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003930 foreach my $Pos (0 .. $#TParams)
3931 {
3932 my $Val = $TParams[$Pos];
3933 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3934
3935 if(not defined $TypeAttr{"Template"})
3936 {
3937 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3938
3939 if($Base{"Type"} eq "TemplateParam"
3940 or defined $Base{"Template"}) {
3941 $TypeAttr{"Template"} = 1;
3942 }
3943 }
3944
3945 if($Tmpl)
3946 {
3947 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3948 {
3949 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3950
3951 if($Val eq $Arg) {
3952 $TypeAttr{"Template"} = 1;
3953 }
3954 }
3955 }
3956 }
3957
3958 if($Tmpl)
3959 {
3960 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3961 {
3962 if($Pos>$#TParams)
3963 {
3964 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3965 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3966 }
3967 }
3968 }
3969 }
3970
3971 if($ADD_TMPL_INSTANCES)
3972 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003973 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003974 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003975 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003976 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003977 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003978 {
3979 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3980 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3981 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003982 }
3983 if(not getTreeAttr_Binf($TypeId))
3984 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003985 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3986 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3987 }
3988 }
3989 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003990 }
3991 }
3992 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003993
3994 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3995
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003996 if(my $Size = getSize($TypeId))
3997 {
3998 $Size = $Size/$BYTE_SIZE;
3999 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004000 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004001 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004002 {
4003 if($ExtraDump)
4004 {
4005 if(not defined $TypeAttr{"Memb"}
4006 and not $Tmpl)
4007 { # declaration only
4008 $TypeAttr{"Forward"} = 1;
4009 }
4010 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004011 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004012
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004013 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004014 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004015 {
4016 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004017 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004018 }
4019 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004020 or $TypeAttr{"Type"} eq "Class")
4021 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004022 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004023 if($Skip) {
4024 return ();
4025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004026 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004027 if(my $Algn = getAlgn($TypeId)) {
4028 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004030 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004031
4032 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4033 {
4034 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004035 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004036 {
4037 if(not isAnon($TypeAttr{"Name"})) {
4038 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4039 }
4040 }
4041 }
4042
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004043 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004044 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4045 {
4046 my @Entries = split(/\n/, $VTable);
4047 foreach (1 .. $#Entries)
4048 {
4049 my $Entry = $Entries[$_];
4050 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004051 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004052 }
4053 }
4054 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004055
4056 if($TypeAttr{"Type"} eq "Enum")
4057 {
4058 if(not $TypeAttr{"NameSpace"})
4059 {
4060 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4061 {
4062 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004063 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004064 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004065 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004066 "Header"=>$TypeAttr{"Header"}
4067 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004068 if(isAnon($TypeAttr{"Name"}))
4069 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004070 if($ExtraDump
4071 or is_target_header($TypeAttr{"Header"}, $Version))
4072 {
4073 %{$Constants{$Version}{$MName}} = (
4074 "Value" => $MVal,
4075 "Header" => $TypeAttr{"Header"}
4076 );
4077 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004078 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004079 }
4080 }
4081 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004082 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004083 {
4084 if(defined $TypedefToAnon{$TypeId}) {
4085 $TypeAttr{"AnonTypedef"} = 1;
4086 }
4087 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004089 return %TypeAttr;
4090}
4091
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004092sub simplifyVTable($)
4093{
4094 my $Content = $_[0];
4095 if($Content=~s/ \[with (.+)]//)
4096 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4097 if(my @Elems = separate_Params($1, 0, 0))
4098 {
4099 foreach my $Elem (@Elems)
4100 {
4101 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4102 {
4103 my ($Arg, $Val) = ($1, $2);
4104
4105 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4106 $Content=~s/,\s*$Arg\b//g;
4107 }
4108 else {
4109 $Content=~s/\b$Arg\b/$Val/g;
4110 }
4111 }
4112 }
4113 }
4114 }
4115
4116 return $Content;
4117}
4118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119sub detect_lang($)
4120{
4121 my $TypeId = $_[0];
4122 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004123 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004124 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4126 }
4127 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004128 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004129 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 while($Fncs)
4131 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004132 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004133 return 1;
4134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004135 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004136 }
4137 }
4138 return 0;
4139}
4140
4141sub setSpec($$)
4142{
4143 my ($TypeId, $TypeAttr) = @_;
4144 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4145 if($Info=~/\s+spec\s+/) {
4146 $TypeAttr->{"Spec"} = 1;
4147 }
4148}
4149
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004150sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004151{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004152 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004153 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004154 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004155 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004156 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004157 my $Pos = 0;
4158 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4159 {
4160 my ($Access, $BInfoId) = ($1, $2);
4161 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004162
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004163 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004164 { # class A<N>:public A<N-1>
4165 next;
4166 }
4167
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004168 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4169 if(not $CType or $CType eq "template_type_parm"
4170 or $CType eq "typename_type")
4171 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004172 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004174 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004175 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004176 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4177 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004178 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004179 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4180 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004181 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004182 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004183 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004184 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4185 }
4186 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004187 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004188 }
4189 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004190 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004191}
4192
4193sub getBinfClassId($)
4194{
4195 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004196 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4197 return $1;
4198 }
4199
4200 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004201}
4202
4203sub unmangledFormat($$)
4204{
4205 my ($Name, $LibVersion) = @_;
4206 $Name = uncover_typedefs($Name, $LibVersion);
4207 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4208 $Name=~s/\(\w+\)(\d)/$1/;
4209 return $Name;
4210}
4211
4212sub modelUnmangled($$)
4213{
4214 my ($InfoId, $Compiler) = @_;
4215 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4216 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4217 }
4218 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4219 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4220 $PureSignature = "~".$PureSignature;
4221 }
4222 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4223 {
4224 my (@Params, @ParamTypes) = ();
4225 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4226 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4227 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4228 }
4229 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4230 { # checking parameters
4231 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004232 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004233 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004234 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004235
4236 if($PName eq "this"
4237 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4238 {
4239 next;
4240 }
4241
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004242 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004244 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004245 }
4246 @ParamTypes = (@ParamTypes, $PTName);
4247 }
4248 if(@ParamTypes) {
4249 $PureSignature .= "(".join(", ", @ParamTypes).")";
4250 }
4251 else
4252 {
4253 if($Compiler eq "MSVC")
4254 {
4255 $PureSignature .= "(void)";
4256 }
4257 else
4258 { # GCC
4259 $PureSignature .= "()";
4260 }
4261 }
4262 $PureSignature = delete_keywords($PureSignature);
4263 }
4264 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4265 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004266 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004267 $PureSignature = $ClassName."::".$PureSignature;
4268 }
4269 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4270 $PureSignature = $NS."::".$PureSignature;
4271 }
4272 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4273 $PureSignature .= " const";
4274 }
4275 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4276 $PureSignature .= " volatile";
4277 }
4278 my $ShowReturn = 0;
4279 if($Compiler eq "MSVC"
4280 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4281 {
4282 $ShowReturn=1;
4283 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004284 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4285 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004286 {
4287 $ShowReturn=1;
4288 }
4289 if($ShowReturn)
4290 { # mangled names for template function specializations include return value
4291 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4292 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004293 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004294 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4295 $PureSignature = $ReturnName." ".$PureSignature;
4296 }
4297 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004298 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004299}
4300
4301sub mangle_symbol($$$)
4302{ # mangling for simple methods
4303 # see gcc-4.6.0/gcc/cp/mangle.c
4304 my ($InfoId, $LibVersion, $Compiler) = @_;
4305 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4306 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4307 }
4308 my $Mangled = "";
4309 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004310 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004311 }
4312 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004313 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004314 }
4315 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4316}
4317
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004318sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004319{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004320 my ($InfoId, $LibVersion) = @_;
4321 return "";
4322}
4323
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004324sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004325{ # see gcc-4.6.0/gcc/cp/mangle.c
4326 my ($InfoId, $LibVersion) = @_;
4327 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004328 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004329 my %Repl = ();# SN_ replacements
4330 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4331 {
4332 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4333 if($MangledClass!~/\AN/) {
4334 $MangledClass = "N".$MangledClass;
4335 }
4336 else {
4337 $MangledClass=~s/E\Z//;
4338 }
4339 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4340 $MangledClass=~s/\AN/NV/;
4341 }
4342 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4343 $MangledClass=~s/\AN/NK/;
4344 }
4345 $Mangled .= $MangledClass;
4346 }
4347 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4348 { # mangled by name due to the absence of structured info
4349 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4350 if($MangledNS!~/\AN/) {
4351 $MangledNS = "N".$MangledNS;
4352 }
4353 else {
4354 $MangledNS=~s/E\Z//;
4355 }
4356 $Mangled .= $MangledNS;
4357 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004358 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004359 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004360 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004361 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004362 foreach (@TPos) {
4363 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4364 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004365 }
4366 elsif($TmplParams)
4367 { # remangling mode
4368 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004369 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004370 }
4371 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4372 $Mangled .= "C1";
4373 }
4374 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4375 $Mangled .= "D0";
4376 }
4377 elsif($ShortName)
4378 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004379 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4380 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004381 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004382 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004383 { # "const" global data is mangled as _ZL...
4384 $Mangled .= "L";
4385 }
4386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004387 if($ShortName=~/\Aoperator(\W.*)\Z/)
4388 {
4389 my $Op = $1;
4390 $Op=~s/\A[ ]+//g;
4391 if(my $OpMngl = $OperatorMangling{$Op}) {
4392 $Mangled .= $OpMngl;
4393 }
4394 else { # conversion operator
4395 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4396 }
4397 }
4398 else {
4399 $Mangled .= length($ShortName).$ShortName;
4400 }
4401 if(@TParams)
4402 { # templates
4403 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004404 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004405 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4406 }
4407 $Mangled .= "E";
4408 }
4409 if(not $ClassId and @TParams) {
4410 add_substitution($ShortName, \%Repl, 0);
4411 }
4412 }
4413 if($ClassId or $NameSpace) {
4414 $Mangled .= "E";
4415 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004416 if(@TParams)
4417 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004418 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004419 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4420 }
4421 }
4422 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4423 {
4424 my @Params = ();
4425 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4426 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4427 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4428 }
4429 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4430 { # checking parameters
4431 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4432 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4433 }
4434 if(not @Params) {
4435 $Mangled .= "v";
4436 }
4437 }
4438 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4439 $Mangled = write_stdcxx_substitution($Mangled);
4440 if($Mangled eq "_Z") {
4441 return "";
4442 }
4443 return $Mangled;
4444}
4445
4446sub correct_incharge($$$)
4447{
4448 my ($InfoId, $LibVersion, $Mangled) = @_;
4449 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4450 {
4451 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004452 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004453 }
4454 }
4455 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4456 {
4457 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004458 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004459 }
4460 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004461 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004462 }
4463 }
4464 return $Mangled;
4465}
4466
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004467sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004468{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004469 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004470 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004471 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004472 return $Name;
4473 }
4474 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004475 while(my $CPos = find_center($TParams, "<"))
4476 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004477 $TParams = substr($TParams, $CPos);
4478 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004479 if($TParams=~s/\A<(.+)>\Z/$1/) {
4480 $Name=~s/<\Q$TParams\E>\Z//;
4481 }
4482 else
4483 { # error
4484 $TParams = "";
4485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004486 return ($Name, $TParams);
4487}
4488
4489sub get_sub_ns($)
4490{
4491 my $Name = $_[0];
4492 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004493 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004494 {
4495 push(@NS, substr($Name, 0, $CPos));
4496 $Name = substr($Name, $CPos);
4497 $Name=~s/\A:://;
4498 }
4499 return (join("::", @NS), $Name);
4500}
4501
4502sub mangle_ns($$$)
4503{
4504 my ($Name, $LibVersion, $Repl) = @_;
4505 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4506 {
4507 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4508 $Mangled=~s/\AN(.+)E\Z/$1/;
4509 return $Mangled;
4510
4511 }
4512 else
4513 {
4514 my ($MangledNS, $SubNS) = ("", "");
4515 ($SubNS, $Name) = get_sub_ns($Name);
4516 if($SubNS) {
4517 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4518 }
4519 $MangledNS .= length($Name).$Name;
4520 add_substitution($MangledNS, $Repl, 0);
4521 return $MangledNS;
4522 }
4523}
4524
4525sub mangle_param($$$)
4526{
4527 my ($PTid, $LibVersion, $Repl) = @_;
4528 my ($MPrefix, $Mangled) = ("", "");
4529 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004530 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004531 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004532 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004533 if(not $BaseType_Name) {
4534 return "";
4535 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004536 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004537 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004538 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4539 while($Suffix=~/(&|\*|const)\Z/)
4540 {
4541 if($Suffix=~s/[ ]*&\Z//) {
4542 $MPrefix .= "R";
4543 }
4544 if($Suffix=~s/[ ]*\*\Z//) {
4545 $MPrefix .= "P";
4546 }
4547 if($Suffix=~s/[ ]*const\Z//)
4548 {
4549 if($MPrefix=~/R|P/
4550 or $Suffix=~/&|\*/) {
4551 $MPrefix .= "K";
4552 }
4553 }
4554 if($Suffix=~s/[ ]*volatile\Z//) {
4555 $MPrefix .= "V";
4556 }
4557 #if($Suffix=~s/[ ]*restrict\Z//) {
4558 #$MPrefix .= "r";
4559 #}
4560 }
4561 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4562 $Mangled .= $Token;
4563 }
4564 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004566 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004567 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004568 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004569 foreach (@TPos) {
4570 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4571 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004572 }
4573 elsif($TmplParams)
4574 { # remangling mode
4575 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004576 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004577 }
4578 my $MangledNS = "";
4579 my ($SubNS, $SName) = get_sub_ns($ShortName);
4580 if($SubNS) {
4581 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4582 }
4583 $MangledNS .= length($SName).$SName;
4584 if(@TParams) {
4585 add_substitution($MangledNS, $Repl, 0);
4586 }
4587 $Mangled .= "N".$MangledNS;
4588 if(@TParams)
4589 { # templates
4590 $Mangled .= "I";
4591 foreach my $TParam (@TParams) {
4592 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4593 }
4594 $Mangled .= "E";
4595 }
4596 $Mangled .= "E";
4597 }
4598 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4599 {
4600 if($BaseType{"Type"} eq "MethodPtr") {
4601 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4602 }
4603 else {
4604 $Mangled .= "PF";
4605 }
4606 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4607 my @Params = keys(%{$BaseType{"Param"}});
4608 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4609 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4610 }
4611 if(not @Params) {
4612 $Mangled .= "v";
4613 }
4614 $Mangled .= "E";
4615 }
4616 elsif($BaseType{"Type"} eq "FieldPtr")
4617 {
4618 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4619 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4620 }
4621 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4622 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4623 {
4624 if($Mangled eq $Optimized)
4625 {
4626 if($ShortName!~/::/)
4627 { # remove "N ... E"
4628 if($MPrefix) {
4629 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4630 }
4631 else {
4632 $Mangled=~s/\AN(.+)E\Z/$1/g;
4633 }
4634 }
4635 }
4636 else {
4637 $Mangled = $Optimized;
4638 }
4639 }
4640 add_substitution($Mangled, $Repl, 1);
4641 return $Mangled;
4642}
4643
4644sub mangle_template_param($$$)
4645{ # types + literals
4646 my ($TParam, $LibVersion, $Repl) = @_;
4647 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4648 return mangle_param($TPTid, $LibVersion, $Repl);
4649 }
4650 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4651 { # class_name<1u>::method(...)
4652 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4653 }
4654 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4655 { # class_name<(signed char)1>::method(...)
4656 return "L".$IntrinsicMangling{$1}.$2."E";
4657 }
4658 elsif($TParam eq "true")
4659 { # class_name<true>::method(...)
4660 return "Lb1E";
4661 }
4662 elsif($TParam eq "false")
4663 { # class_name<true>::method(...)
4664 return "Lb0E";
4665 }
4666 else { # internal error
4667 return length($TParam).$TParam;
4668 }
4669}
4670
4671sub add_substitution($$$)
4672{
4673 my ($Value, $Repl, $Rec) = @_;
4674 if($Rec)
4675 { # subtypes
4676 my @Subs = ($Value);
4677 while($Value=~s/\A(R|P|K)//) {
4678 push(@Subs, $Value);
4679 }
4680 foreach (reverse(@Subs)) {
4681 add_substitution($_, $Repl, 0);
4682 }
4683 return;
4684 }
4685 return if($Value=~/\AS(\d*)_\Z/);
4686 $Value=~s/\AN(.+)E\Z/$1/g;
4687 return if(defined $Repl->{$Value});
4688 return if(length($Value)<=1);
4689 return if($StdcxxMangling{$Value});
4690 # check for duplicates
4691 my $Base = $Value;
4692 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4693 {
4694 my $Num = $Repl->{$Type};
4695 my $Replace = macro_mangle($Num);
4696 $Base=~s/\Q$Replace\E/$Type/;
4697 }
4698 if(my $OldNum = $Repl->{$Base})
4699 {
4700 $Repl->{$Value} = $OldNum;
4701 return;
4702 }
4703 my @Repls = sort {$b<=>$a} values(%{$Repl});
4704 if(@Repls) {
4705 $Repl->{$Value} = $Repls[0]+1;
4706 }
4707 else {
4708 $Repl->{$Value} = -1;
4709 }
4710 # register duplicates
4711 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004712 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004713 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4714 {
4715 next if($Base eq $Type);
4716 my $Num = $Repl->{$Type};
4717 my $Replace = macro_mangle($Num);
4718 $Base=~s/\Q$Type\E/$Replace/;
4719 $Repl->{$Base} = $Repl->{$Value};
4720 }
4721}
4722
4723sub macro_mangle($)
4724{
4725 my $Num = $_[0];
4726 if($Num==-1) {
4727 return "S_";
4728 }
4729 else
4730 {
4731 my $Code = "";
4732 if($Num<10)
4733 { # S0_, S1_, S2_, ...
4734 $Code = $Num;
4735 }
4736 elsif($Num>=10 and $Num<=35)
4737 { # SA_, SB_, SC_, ...
4738 $Code = chr(55+$Num);
4739 }
4740 else
4741 { # S10_, S11_, S12_
4742 $Code = $Num-26; # 26 is length of english alphabet
4743 }
4744 return "S".$Code."_";
4745 }
4746}
4747
4748sub write_stdcxx_substitution($)
4749{
4750 my $Mangled = $_[0];
4751 if($StdcxxMangling{$Mangled}) {
4752 return $StdcxxMangling{$Mangled};
4753 }
4754 else
4755 {
4756 my @Repls = keys(%StdcxxMangling);
4757 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4758 foreach my $MangledType (@Repls)
4759 {
4760 my $Replace = $StdcxxMangling{$MangledType};
4761 #if($Mangled!~/$Replace/) {
4762 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4763 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4764 #}
4765 }
4766 }
4767 return $Mangled;
4768}
4769
4770sub write_substitution($$)
4771{
4772 my ($Mangled, $Repl) = @_;
4773 if(defined $Repl->{$Mangled}
4774 and my $MnglNum = $Repl->{$Mangled}) {
4775 $Mangled = macro_mangle($MnglNum);
4776 }
4777 else
4778 {
4779 my @Repls = keys(%{$Repl});
4780 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4781 # FIXME: how to apply replacements? by num or by pos
4782 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4783 foreach my $MangledType (@Repls)
4784 {
4785 my $Replace = macro_mangle($Repl->{$MangledType});
4786 if($Mangled!~/$Replace/) {
4787 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4788 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4789 }
4790 }
4791 }
4792 return $Mangled;
4793}
4794
4795sub delete_keywords($)
4796{
4797 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004798 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004799 return $TypeName;
4800}
4801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004802sub uncover_typedefs($$)
4803{
4804 my ($TypeName, $LibVersion) = @_;
4805 return "" if(not $TypeName);
4806 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4807 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4808 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004809 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004810 while($TypeName_New ne $TypeName_Pre)
4811 {
4812 $TypeName_Pre = $TypeName_New;
4813 my $TypeName_Copy = $TypeName_New;
4814 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004815 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004816 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004817 if(not $Intrinsic_Keywords{$1}) {
4818 $Words{$1} = 1;
4819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004820 }
4821 foreach my $Word (keys(%Words))
4822 {
4823 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4824 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004825 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004826 if($BaseType_Name=~/\([\*]+\)/)
4827 { # FuncPtr
4828 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4829 {
4830 my $Type_Suffix = $1;
4831 $TypeName_New = $BaseType_Name;
4832 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004833 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004834 }
4835 }
4836 }
4837 else
4838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004839 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004840 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004841 }
4842 }
4843 }
4844 }
4845 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4846}
4847
4848sub isInternal($)
4849{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004850 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4851 {
4852 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4853 {
4854 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4855 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4856 return 1;
4857 }
4858 }
4859 }
4860 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004861}
4862
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004863sub getDataVal($$)
4864{
4865 my ($InfoId, $TypeId) = @_;
4866 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4867 {
4868 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4869 {
4870 if(defined $LibInfo{$Version}{"info_type"}{$1}
4871 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004872 {
4873 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004874 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004875 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4876 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004877 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004878 if(my $Addr = getTreeAttr_Op($1)) {
4879 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004880 }
4881 }
4882 }
4883 }
4884 else {
4885 return getInitVal($1, $TypeId);
4886 }
4887 }
4888 }
4889 return undef;
4890}
4891
4892sub getInitVal($$)
4893{
4894 my ($InfoId, $TypeId) = @_;
4895 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4896 {
4897 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4898 {
4899 if($InfoType eq "integer_cst")
4900 {
4901 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004902 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004903 { # characters
4904 $Val = chr($Val);
4905 }
4906 return $Val;
4907 }
4908 elsif($InfoType eq "string_cst") {
4909 return getNodeStrCst($InfoId);
4910 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004911 elsif($InfoType eq "var_decl")
4912 {
4913 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4914 return $Name;
4915 }
4916 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004917 }
4918 }
4919 return undef;
4920}
4921
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004922sub set_Class_And_Namespace($)
4923{
4924 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004925 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004926 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004927 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004928 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004929 my $NSInfoId = $1;
4930 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4931 {
4932 if($InfoType eq "namespace_decl") {
4933 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4934 }
4935 elsif($InfoType eq "record_type") {
4936 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4937 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004939 }
4940 }
4941 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4942 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004943 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004944 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004945 { # skip
4946 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004949
4950 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004951}
4952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004953sub debugMangling($)
4954{
4955 my $LibVersion = $_[0];
4956 my %Mangled = ();
4957 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4958 {
4959 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4960 {
4961 if($Mngl=~/\A(_Z|\?)/) {
4962 $Mangled{$Mngl}=$InfoId;
4963 }
4964 }
4965 }
4966 translateSymbols(keys(%Mangled), $LibVersion);
4967 foreach my $Mngl (keys(%Mangled))
4968 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004969 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4970 my $U2 = $tr_name{$Mngl};
4971 if($U1 ne $U2) {
4972 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004973 }
4974 }
4975}
4976
4977sub linkSymbol($)
4978{ # link symbols from shared libraries
4979 # with the symbols from header files
4980 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004981 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004982 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004983 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4984 or $EMERGENCY_MODE_48)
4985 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4986 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03004987 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004988 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004989 {
4990 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4991 return correct_incharge($InfoId, $Version, $Mangled);
4992 }
4993 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004994 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004995 or not $BinaryOnly
4996 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004997 { # 1. --headers-only mode
4998 # 2. not mangled src-only symbols
4999 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5000 return $Mangled;
5001 }
5002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005003 }
5004 return "";
5005}
5006
5007sub setLanguage($$)
5008{
5009 my ($LibVersion, $Lang) = @_;
5010 if(not $UserLang) {
5011 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5012 }
5013}
5014
5015sub getSymbolInfo($)
5016{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005017 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005018 if(isInternal($InfoId)) {
5019 return;
5020 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005021 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5022 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005023 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5024 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005025 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005026 return;
5027 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005028 setFuncAccess($InfoId);
5029 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005030 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5031 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005032 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005033 return;
5034 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005035
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005036 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005037 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005038 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005039 if(not defined $TypeInfo{$Version}{$Return}
5040 or not $TypeInfo{$Version}{$Return}{"Name"})
5041 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005042 delete($SymbolInfo{$Version}{$InfoId});
5043 return;
5044 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005045 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005046 }
5047 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5048 {
5049 if(defined $MissedTypedef{$Version}{$Rid})
5050 {
5051 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5052 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5053 }
5054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005055 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005056 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5057 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005058 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005059 my $Orig = getFuncOrig($InfoId);
5060 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005061 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5062 {
5063 delete($SymbolInfo{$Version}{$InfoId});
5064 return;
5065 }
5066
5067 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005068 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005069 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005070 return;
5071 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005072
5073 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005075 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5076
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005077 my @TParams = getTParams($Orig, "Func");
5078 if(not @TParams)
5079 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005080 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005081 return;
5082 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005083 foreach my $Pos (0 .. $#TParams)
5084 {
5085 my $Val = $TParams[$Pos];
5086 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5087
5088 if($Tmpl)
5089 {
5090 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5091 {
5092 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5093 }
5094 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005095 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005096
5097 if($Tmpl)
5098 {
5099 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5100 {
5101 if($Pos>$#TParams)
5102 {
5103 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5104 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5105 }
5106 }
5107 }
5108
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005109 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5110 { # operator<< <T>, operator>> <T>
5111 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5112 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005113 if(@TParams) {
5114 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5115 }
5116 else {
5117 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5118 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005119 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005120 }
5121 else
5122 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005123 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005125 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5126 {
5127 if($OSgroup eq "windows")
5128 { # cut the offset
5129 $MnglName=~s/\@\d+\Z//g;
5130 }
5131 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5132
5133 # NOTE: mangling of some symbols may change depending on GCC version
5134 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5135 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5136 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005137
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005138 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005139 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005141 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005142 return;
5143 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005144 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005146 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005147 if($Skip)
5148 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005149 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005150 return;
5151 }
5152 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005153 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5154 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5155 }
5156
5157 if(set_Class_And_Namespace($InfoId))
5158 {
5159 delete($SymbolInfo{$Version}{$InfoId});
5160 return;
5161 }
5162
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005163 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5164 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005165 if(not defined $TypeInfo{$Version}{$ClassId}
5166 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5167 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005168 delete($SymbolInfo{$Version}{$InfoId});
5169 return;
5170 }
5171 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005172 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5173 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005174 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005175 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005176 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005177 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005178 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005179 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005180 }
5181 if($COMMON_LANGUAGE{$Version} eq "C++")
5182 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 # C++ or --headers-only mode
5184 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005186 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5187 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005188 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005189 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005191 if(my $Mangled = linkSymbol($InfoId)) {
5192 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005193 }
5194 }
5195 if($OStarget eq "windows")
5196 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005197 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005198 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005199 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005200 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005201 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005203 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 }
5205 }
5206 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005207 else
5208 { # not mangled in C
5209 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5210 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005211 if(not $CheckHeadersOnly
5212 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5213 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5214 {
5215 my $Incorrect = 0;
5216
5217 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5218 {
5219 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5220 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5221 { # mangled in the TU dump, but not mangled in the library
5222 $Incorrect = 1;
5223 }
5224 }
5225 else
5226 {
5227 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5228 { # all C++ functions are not mangled in the TU dump
5229 $Incorrect = 1;
5230 }
5231 }
5232 if($Incorrect)
5233 {
5234 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5235 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5236 }
5237 }
5238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005239 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005240 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005241 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 return;
5243 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005244 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005245 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005246 { # identify virtual and pure virtual functions
5247 # NOTE: constructors cannot be virtual
5248 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5249 # in the TU dump, so taking it from the original symbol
5250 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5251 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5252 { # NOTE: D2 destructors are not present in a v-table
5253 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 if(isInline($InfoId)) {
5257 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005258 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005259 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005260 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005262 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5263 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005265 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005266 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005267 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005268 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005269 }
5270 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005271 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5272 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005273 if(not $ExtraDump)
5274 {
5275 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5276 { # non-target symbols
5277 delete($SymbolInfo{$Version}{$InfoId});
5278 return;
5279 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005282 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5283 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5284 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5285 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005286 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005287 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5288 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005289 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 return;
5291 }
5292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005295 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005296 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 return;
5299 }
5300 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005301 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 }
5303 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005304 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5305 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5306 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5309 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005310 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005311 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005312 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005313 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005314 }
5315 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005316 if(getFuncLink($InfoId) eq "Static") {
5317 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005319 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5320 {
5321 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5322 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005323 if($Unmangled=~/\.\_\d/)
5324 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005325 delete($SymbolInfo{$Version}{$InfoId});
5326 return;
5327 }
5328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005329 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005330
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005331 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5332 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005334 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5335 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005336 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005337
5338 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5339 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5340 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005341
5342 if($ExtraDump) {
5343 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5344 }
5345}
5346
5347sub guessHeader($)
5348{
5349 my $InfoId = $_[0];
5350 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5351 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5352 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5353 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5354 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5355 {
5356 if(get_filename($HPath) eq $Header)
5357 {
5358 my $HDir = get_filename(get_dirname($HPath));
5359 if($HDir ne "include"
5360 and $HDir=~/\A[a-z]+\Z/i) {
5361 return join_P($HDir, $Header);
5362 }
5363 }
5364 }
5365 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366}
5367
5368sub isInline($)
5369{ # "body: undefined" in the tree
5370 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005371 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5372 {
5373 if($Info=~/ undefined /i) {
5374 return 0;
5375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005376 }
5377 return 1;
5378}
5379
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005380sub hasThrow($)
5381{
5382 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5383 {
5384 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5385 return getTreeAttr_Unql($1, "unql");
5386 }
5387 }
5388 return 1;
5389}
5390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391sub getTypeId($)
5392{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005393 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5394 {
5395 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5396 return $1;
5397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005398 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005399 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005400}
5401
5402sub setTypeMemb($$)
5403{
5404 my ($TypeId, $TypeAttr) = @_;
5405 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005406 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005407 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005408 if($TypeType eq "Enum")
5409 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005410 my $MInfoId = getTreeAttr_Csts($TypeId);
5411 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005413 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5414 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005415 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005416 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5417 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005418 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005419 }
5420 }
5421 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5422 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005423 my $MInfoId = getTreeAttr_Flds($TypeId);
5424 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005425 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005426 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5427 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005428 if(not $IType or $IType ne "field_decl")
5429 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005430
5431 if($IType eq "var_decl")
5432 { # static field
5433 $StaticFields = 1;
5434 }
5435
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005436 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005437 next;
5438 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005439 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005440 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005441 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005442 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 }
5444 if(not $StructMembName)
5445 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005446 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005448 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005449 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5450 if(isAnon($UnnamedTName))
5451 { # rename unnamed fields to unnamed0, unnamed1, ...
5452 $StructMembName = "unnamed".($UnnamedPos++);
5453 }
5454 }
5455 }
5456 if(not $StructMembName)
5457 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005458 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005459 next;
5460 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005461 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005462 if(defined $MissedTypedef{$Version}{$MembTypeId})
5463 {
5464 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5465 $MembTypeId = $AddedTid;
5466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005468
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005469 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5470 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005471 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005472 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005473 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5474 }
5475 if($MInfo=~/spec:\s*mutable /)
5476 { # mutable fields
5477 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005478 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005479 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005480 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5481 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005482 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005483 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005484 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005485 }
5486 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005487 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005488 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5489 { # template
5490 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5491 }
5492 else {
5493 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005496
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005497 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005498 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499 }
5500 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005501
5502 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005503}
5504
5505sub setFuncParams($)
5506{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005507 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005508 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005509
5510 my $FType = getFuncType($InfoId);
5511
5512 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005514 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5515 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005516 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005517 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005518 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005520 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005521 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005524 else
5525 { # skip
5526 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005528 # skip "this"-parameter
5529 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005530 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005531 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005532 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005533 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005534 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5535 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5536 if(not $ParamName)
5537 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005538 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005539 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005540 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5541 {
5542 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5543 $ParamTypeId = $AddedTid;
5544 }
5545 }
5546 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 if(not $PType or $PType eq "Unknown") {
5548 return 1;
5549 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005550 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005551 if(not $PTName) {
5552 return 1;
5553 }
5554 if($PTName eq "void") {
5555 last;
5556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005558 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005560 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 $ParamInfoId = getNextElem($ParamInfoId);
5562 next;
5563 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005564 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005565
5566 if(my %Base = get_BaseType($ParamTypeId, $Version))
5567 {
5568 if(defined $Base{"Template"}) {
5569 return 1;
5570 }
5571 }
5572
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005574 if(my $Algn = getAlgn($ParamInfoId)) {
5575 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005577 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5578 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005580 }
5581 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005582 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005583 if($ParamName ne "this" or $FType ne "Method") {
5584 $PPos += 1;
5585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005586 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005587 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005588 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005589 }
5590 return 0;
5591}
5592
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005593sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005594{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005595 my ($InfoId, $Vtt_Pos) = @_;
5596 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005597 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005598 my $FType = getFuncType($InfoId);
5599
5600 if($FType eq "Method")
5601 {
5602 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005603 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005604 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005605 if(not $ParamListElemId)
5606 { # foo(...)
5607 return 1;
5608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005610 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005611 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005612 { # actual params: may differ from formal args
5613 # formal int*const
5614 # actual: int*
5615 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005616 {
5617 $Vtt_Pos=-1;
5618 $ParamListElemId = getNextElem($ParamListElemId);
5619 next;
5620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005621 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5622 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005623 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005624 $HaveVoid = 1;
5625 last;
5626 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005627 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005629 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5630 {
5631 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5632 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5633 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005634 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005635 }
5636 }
5637 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5638 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005639 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005640 { # params
5641 if($OldId ne $ParamTypeId)
5642 {
5643 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5644 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5645
5646 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5647 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5648 }
5649 }
5650 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005651 }
5652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005653 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005654 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005655 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5656 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005657 if($PurpType eq "nop_expr")
5658 { # func ( const char* arg = (const char*)(void*)0 )
5659 $PurpId = getTreeAttr_Op($PurpId);
5660 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005661 my $Val = getInitVal($PurpId, $ParamTypeId);
5662 if(defined $Val) {
5663 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005665 }
5666 }
5667 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005668 if($Pos!=0 or $FType ne "Method") {
5669 $PPos += 1;
5670 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005671 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005672 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005673 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005674}
5675
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005676sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005677{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005678 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5679 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005680 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5681 return $1;
5682 }
5683 }
5684 return "";
5685}
5686
5687sub getTreeAttr_Chain($)
5688{
5689 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5690 {
5691 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5692 return $1;
5693 }
5694 }
5695 return "";
5696}
5697
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005698sub getTreeAttr_Unql($)
5699{
5700 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5701 {
5702 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5703 return $1;
5704 }
5705 }
5706 return "";
5707}
5708
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005709sub getTreeAttr_Scpe($)
5710{
5711 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5712 {
5713 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5714 return $1;
5715 }
5716 }
5717 return "";
5718}
5719
5720sub getTreeAttr_Type($)
5721{
5722 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5723 {
5724 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5725 return $1;
5726 }
5727 }
5728 return "";
5729}
5730
5731sub getTreeAttr_Name($)
5732{
5733 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5734 {
5735 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5736 return $1;
5737 }
5738 }
5739 return "";
5740}
5741
5742sub getTreeAttr_Mngl($)
5743{
5744 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5745 {
5746 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5747 return $1;
5748 }
5749 }
5750 return "";
5751}
5752
5753sub getTreeAttr_Prms($)
5754{
5755 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5756 {
5757 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5758 return $1;
5759 }
5760 }
5761 return "";
5762}
5763
5764sub getTreeAttr_Fncs($)
5765{
5766 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5767 {
5768 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5769 return $1;
5770 }
5771 }
5772 return "";
5773}
5774
5775sub getTreeAttr_Csts($)
5776{
5777 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5778 {
5779 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5780 return $1;
5781 }
5782 }
5783 return "";
5784}
5785
5786sub getTreeAttr_Purp($)
5787{
5788 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5789 {
5790 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5791 return $1;
5792 }
5793 }
5794 return "";
5795}
5796
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005797sub getTreeAttr_Op($)
5798{
5799 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5800 {
5801 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5802 return $1;
5803 }
5804 }
5805 return "";
5806}
5807
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005808sub getTreeAttr_Valu($)
5809{
5810 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5811 {
5812 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5813 return $1;
5814 }
5815 }
5816 return "";
5817}
5818
5819sub getTreeAttr_Flds($)
5820{
5821 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5822 {
5823 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5824 return $1;
5825 }
5826 }
5827 return "";
5828}
5829
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005830sub getTreeAttr_Binf($)
5831{
5832 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5833 {
5834 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5835 return $1;
5836 }
5837 }
5838 return "";
5839}
5840
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005841sub getTreeAttr_Args($)
5842{
5843 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5844 {
5845 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005846 return $1;
5847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005848 }
5849 return "";
5850}
5851
5852sub getTreeValue($)
5853{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005854 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5855 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005856 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5857 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005859 }
5860 return "";
5861}
5862
5863sub getTreeAccess($)
5864{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005865 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005866 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005867 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5868 {
5869 my $Access = $1;
5870 if($Access eq "prot") {
5871 return "protected";
5872 }
5873 elsif($Access eq "priv") {
5874 return "private";
5875 }
5876 }
5877 elsif($Info=~/ protected /)
5878 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005879 return "protected";
5880 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005881 elsif($Info=~/ private /)
5882 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883 return "private";
5884 }
5885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005886 return "public";
5887}
5888
5889sub setFuncAccess($)
5890{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005891 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005892 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005893 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005894 }
5895 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005896 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897 }
5898}
5899
5900sub setTypeAccess($$)
5901{
5902 my ($TypeId, $TypeAttr) = @_;
5903 my $Access = getTreeAccess($TypeId);
5904 if($Access eq "protected") {
5905 $TypeAttr->{"Protected"} = 1;
5906 }
5907 elsif($Access eq "private") {
5908 $TypeAttr->{"Private"} = 1;
5909 }
5910}
5911
5912sub setFuncKind($)
5913{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005914 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5915 {
5916 if($Info=~/pseudo tmpl/) {
5917 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5918 }
5919 elsif($Info=~/ constructor /) {
5920 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5921 }
5922 elsif($Info=~/ destructor /) {
5923 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005925 }
5926}
5927
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005928sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005930 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5931 {
5932 if($Info=~/spec[ ]*:[ ]*pure /) {
5933 return "PureVirt";
5934 }
5935 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5936 return "Virt";
5937 }
5938 elsif($Info=~/ pure\s+virtual /)
5939 { # support for old GCC versions
5940 return "PureVirt";
5941 }
5942 elsif($Info=~/ virtual /)
5943 { # support for old GCC versions
5944 return "Virt";
5945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005946 }
5947 return "";
5948}
5949
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950sub getFuncLink($)
5951{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005952 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5953 {
5954 if($Info=~/link[ ]*:[ ]*static /) {
5955 return "Static";
5956 }
5957 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005958 return $1;
5959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005960 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005961 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962}
5963
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005964sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005965{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005966 my ($Symbol, $LibVersion) = @_;
5967 return "" if(not $Symbol or not $LibVersion);
5968 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5969 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005970 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005971 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5972 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5973 }
5974 }
5975 if($NS)
5976 {
5977 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5978 return $NS;
5979 }
5980 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005981 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005982 while($NS=~s/::[^:]+\Z//)
5983 {
5984 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5985 return $NS;
5986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 }
5988 }
5989 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005990
5991 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005992}
5993
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005994sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995{
5996 my ($TypeName, $LibVersion) = @_;
5997 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005998 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006000 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6001 return $NS;
6002 }
6003 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006004 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006005 while($NS=~s/::[^:]+\Z//)
6006 {
6007 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6008 return $NS;
6009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010 }
6011 }
6012 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006013 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014}
6015
6016sub getNameSpace($)
6017{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006018 my $InfoId = $_[0];
6019 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006021 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006023 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006024 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006025 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6026 {
6027 my $NameSpace = getTreeStr($1);
6028 if($NameSpace eq "::")
6029 { # global namespace
6030 return "";
6031 }
6032 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6033 $NameSpace = $BaseNameSpace."::".$NameSpace;
6034 }
6035 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6036 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006037 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006038 else {
6039 return "";
6040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006041 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006042 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006043 { # inside data type
6044 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6045 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006048 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006049 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050}
6051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052sub getEnumMembVal($)
6053{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006054 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6057 {
6058 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6059 {
6060 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6061 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6062 return getTreeValue($1);
6063 }
6064 else
6065 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6066 return getTreeValue($1);
6067 }
6068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006069 }
6070 }
6071 return "";
6072}
6073
6074sub getSize($)
6075{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006076 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6077 {
6078 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6079 return getTreeValue($1);
6080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006081 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006082 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006083}
6084
6085sub getAlgn($)
6086{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006087 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6088 {
6089 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6090 return $1;
6091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006092 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006093 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006094}
6095
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006096sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006097{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006098 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6099 {
6100 if($Info=~/ bitfield /) {
6101 return getSize($_[0]);
6102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006103 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006104 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006105}
6106
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006107sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006109 if(my $Chan = getTreeAttr_Chan($_[0])) {
6110 return $Chan;
6111 }
6112 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6113 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006115 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006116}
6117
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006118sub registerHeader($$)
6119{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006121 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006122 return "";
6123 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006124 if(is_abs($Header) and not -f $Header)
6125 { # incorrect absolute path
6126 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006128 if(skipHeader($Header, $LibVersion))
6129 { # skip
6130 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6133 {
6134 detect_header_includes($Header_Path, $LibVersion);
6135
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006136 if(defined $Tolerance and $Tolerance=~/3/)
6137 { # 3 - skip headers that include non-Linux headers
6138 if($OSgroup ne "windows")
6139 {
6140 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6141 {
6142 if(specificHeader($Inc, "windows")) {
6143 return "";
6144 }
6145 }
6146 }
6147 }
6148
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006149 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6150 { # redirect
6151 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6152 or skipHeader($RHeader_Path, $LibVersion))
6153 { # skip
6154 return "";
6155 }
6156 $Header_Path = $RHeader_Path;
6157 }
6158 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6159 { # skip
6160 return "";
6161 }
6162
6163 if(my $HName = get_filename($Header_Path))
6164 { # register
6165 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6166 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6167 }
6168
6169 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6170 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006171 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006172 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006173 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006174 }
6175
6176 if($CheckHeadersOnly
6177 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6178 { # /usr/include/c++/4.6.1/...
6179 $STDCXX_TESTING = 1;
6180 }
6181
6182 return $Header_Path;
6183 }
6184 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006185}
6186
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006187sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006188{
6189 my ($Dir, $WithDeps, $LibVersion) = @_;
6190 $Dir=~s/[\/\\]+\Z//g;
6191 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006193
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006194 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006195 if($WithDeps)
6196 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6198 return;
6199 }
6200 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6201 $Mode = "DepsOnly";
6202 }
6203 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006204 else
6205 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006206 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6207 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6208 return;
6209 }
6210 }
6211 $Header_Dependency{$LibVersion}{$Dir} = 1;
6212 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6213 if($Mode eq "DepsOnly")
6214 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006215 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216 $Header_Dependency{$LibVersion}{$Path} = 1;
6217 }
6218 return;
6219 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006220 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006221 {
6222 if($WithDeps)
6223 {
6224 my $SubDir = $Path;
6225 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6226 { # register all sub directories
6227 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6228 }
6229 }
6230 next if(is_not_header($Path));
6231 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006232 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006233 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006234 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6235 }
6236 }
6237 if(get_filename($Dir) eq "include")
6238 { # search for "lib/include/" directory
6239 my $LibDir = $Dir;
6240 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006241 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006242 }
6243 }
6244}
6245
6246sub parse_redirect($$$)
6247{
6248 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006249 my @Errors = ();
6250 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6251 push(@Errors, $1);
6252 }
6253 my $Redirect = "";
6254 foreach (@Errors)
6255 {
6256 s/\s{2,}/ /g;
6257 if(/(only|must\ include
6258 |update\ to\ include
6259 |replaced\ with
6260 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006261 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006262 {
6263 $Redirect = $2;
6264 last;
6265 }
6266 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6267 {
6268 $Redirect = $2;
6269 last;
6270 }
6271 elsif(/this\ header\ should\ not\ be\ used
6272 |programs\ should\ not\ directly\ include
6273 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6274 |is\ not\ supported\ API\ for\ general\ use
6275 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006276 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006277 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6278 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6279 }
6280 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006281 if($Redirect)
6282 {
6283 $Redirect=~s/\A<//g;
6284 $Redirect=~s/>\Z//g;
6285 }
6286 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006287}
6288
6289sub parse_includes($$)
6290{
6291 my ($Content, $Path) = @_;
6292 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006293 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006294 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006295 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006296 my $Method = substr($Header, 0, 1, "");
6297 substr($Header, length($Header)-1, 1, "");
6298 $Header = path_format($Header, $OSgroup);
6299 if($Method eq "\"" or is_abs($Header))
6300 {
6301 if(-e join_P(get_dirname($Path), $Header))
6302 { # relative path exists
6303 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006304 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006305 else
6306 { # include "..." that doesn't exist is equal to include <...>
6307 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006309 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006310 else {
6311 $Includes{$Header} = 1;
6312 }
6313 }
6314 if($ExtraInfo)
6315 {
6316 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6317 { # FT_FREETYPE_H
6318 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006319 }
6320 }
6321 return \%Includes;
6322}
6323
6324sub ignore_path($)
6325{
6326 my $Path = $_[0];
6327 if($Path=~/\~\Z/)
6328 {# skipping system backup files
6329 return 1;
6330 }
6331 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6332 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6333 return 1;
6334 }
6335 return 0;
6336}
6337
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006338sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006339{
6340 my ($ArrRef, $W) = @_;
6341 return if(length($W)<2);
6342 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6343}
6344
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006345sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006346{
6347 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349 $H1=~s/\.[a-z]+\Z//ig;
6350 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006351
6352 my $Hname1 = get_filename($H1);
6353 my $Hname2 = get_filename($H2);
6354 my $HDir1 = get_dirname($H1);
6355 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006356 my $Dirname1 = get_filename($HDir1);
6357 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006358
6359 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6360 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6361
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006362 if($_[0] eq $_[1]
6363 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006364 return 0;
6365 }
6366 elsif($H1=~/\A\Q$H2\E/) {
6367 return 1;
6368 }
6369 elsif($H2=~/\A\Q$H1\E/) {
6370 return -1;
6371 }
6372 elsif($HDir1=~/\Q$Hname1\E/i
6373 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006374 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006375 return -1;
6376 }
6377 elsif($HDir2=~/\Q$Hname2\E/i
6378 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006379 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006380 return 1;
6381 }
6382 elsif($Hname1=~/\Q$Dirname1\E/i
6383 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006384 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006385 return -1;
6386 }
6387 elsif($Hname2=~/\Q$Dirname2\E/i
6388 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006389 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006390 return 1;
6391 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006392 elsif($Hname1=~/(config|lib|util)/i
6393 and $Hname2!~/(config|lib|util)/i)
6394 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006395 return -1;
6396 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006397 elsif($Hname2=~/(config|lib|util)/i
6398 and $Hname1!~/(config|lib|util)/i)
6399 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006400 return 1;
6401 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006402 else
6403 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006404 my $R1 = checkRelevance($H1);
6405 my $R2 = checkRelevance($H2);
6406 if($R1 and not $R2)
6407 { # libebook/e-book.h
6408 return -1;
6409 }
6410 elsif($R2 and not $R1)
6411 { # libebook/e-book.h
6412 return 1;
6413 }
6414 else
6415 {
6416 return (lc($H1) cmp lc($H2));
6417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006418 }
6419}
6420
6421sub searchForHeaders($)
6422{
6423 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006424
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006425 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006426 registerGccHeaders();
6427
6428 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6429 { # c++ standard include paths
6430 registerCppHeaders();
6431 }
6432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006434 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6435 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006436 {
6437 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006438 if($SystemRoot)
6439 {
6440 if(is_abs($Path)) {
6441 $Path = $SystemRoot.$Path;
6442 }
6443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006444 if(not -e $Path) {
6445 exitStatus("Access_Error", "can't access \'$Path\'");
6446 }
6447 elsif(-f $Path) {
6448 exitStatus("Access_Error", "\'$Path\' - not a directory");
6449 }
6450 elsif(-d $Path)
6451 {
6452 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006453 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006454 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6455 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006456 }
6457 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006458 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006459 }
6460 }
6461 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006462 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6464 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006466 # registering directories
6467 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6468 {
6469 next if(not -e $Path);
6470 $Path = get_abs_path($Path);
6471 $Path = path_format($Path, $OSgroup);
6472 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006473 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006474 }
6475 elsif(-f $Path)
6476 {
6477 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006478 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006479 and not $LocalIncludes{$Dir})
6480 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006481 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006482 # if(my $OutDir = get_dirname($Dir))
6483 # { # registering the outer directory
6484 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6485 # and not $LocalIncludes{$OutDir}) {
6486 # registerDir($OutDir, 0, $LibVersion);
6487 # }
6488 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006489 }
6490 }
6491 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006492
6493 # clean memory
6494 %RegisteredDirs = ();
6495
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006496 # registering headers
6497 my $Position = 0;
6498 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6499 {
6500 if(is_abs($Dest) and not -e $Dest) {
6501 exitStatus("Access_Error", "can't access \'$Dest\'");
6502 }
6503 $Dest = path_format($Dest, $OSgroup);
6504 if(is_header($Dest, 1, $LibVersion))
6505 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006506 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006507 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6508 }
6509 }
6510 elsif(-d $Dest)
6511 {
6512 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006513 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006514 {
6515 next if(ignore_path($Path));
6516 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006517 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006518 push(@Registered, $HPath);
6519 }
6520 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006521 @Registered = sort {sortHeaders($a, $b)} @Registered;
6522 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006523 foreach my $Path (@Registered) {
6524 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6525 }
6526 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006527 elsif(not defined $SkipUnidentified) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006528 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6529 }
6530 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006531
6532 if(defined $Tolerance and $Tolerance=~/4/)
6533 { # 4 - skip headers included by others
6534 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6535 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006536 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006537 delete($Registered_Headers{$LibVersion}{$Path});
6538 }
6539 }
6540 }
6541
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006542 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6543 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006544 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006545 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006546 if(is_abs($Header) and not -f $Header) {
6547 exitStatus("Access_Error", "can't access file \'$Header\'");
6548 }
6549 $Header = path_format($Header, $OSgroup);
6550 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6551 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006552 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006553 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006554 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006555 elsif($SkipUnidentified) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006556 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006558 }
6559 }
6560 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6561 { # set relative paths (for duplicates)
6562 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6563 { # search for duplicates
6564 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6565 my $Prefix = get_dirname($FirstPath);
6566 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6567 { # detect a shortest distinguishing prefix
6568 my $NewPrefix = $1;
6569 my %Identity = ();
6570 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6571 {
6572 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6573 $Identity{$Path} = $1;
6574 }
6575 }
6576 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006577 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006578 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6579 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6580 }
6581 last;
6582 }
6583 $Prefix = $NewPrefix; # increase prefix
6584 }
6585 }
6586 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006587
6588 # clean memory
6589 %HeaderName_Paths = ();
6590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006591 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6592 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006593 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006594 my ($Pos, $PairPos) = (-1, -1);
6595 my ($Path, $PairPath) = ();
6596 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6597 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6598 foreach my $Header_Path (@Paths)
6599 {
6600 if(get_filename($Header_Path) eq $PairName)
6601 {
6602 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6603 $PairPath = $Header_Path;
6604 }
6605 if(get_filename($Header_Path) eq $HeaderName)
6606 {
6607 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6608 $Path = $Header_Path;
6609 }
6610 }
6611 if($PairPos!=-1 and $Pos!=-1
6612 and int($PairPos)<int($Pos))
6613 {
6614 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6615 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6616 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6617 }
6618 }
6619 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6620 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6621 }
6622}
6623
6624sub detect_real_includes($$)
6625{
6626 my ($AbsPath, $LibVersion) = @_;
6627 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6628 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6629 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6630 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6631 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006632 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006634 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6635 return () if(not $Path);
6636 open(PREPROC, $Path);
6637 while(<PREPROC>)
6638 {
6639 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6640 {
6641 my $Include = path_format($1, $OSgroup);
6642 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6643 next;
6644 }
6645 if($Include eq $AbsPath) {
6646 next;
6647 }
6648 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6649 }
6650 }
6651 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006652 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6653}
6654
6655sub detect_header_includes($$)
6656{
6657 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006658 return if(not $LibVersion or not $Path);
6659 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6660 return;
6661 }
6662 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6663
6664 if(not -e $Path) {
6665 return;
6666 }
6667
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006668 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006669 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6670 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006671 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 {
6673 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006674 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006675 }
6676 if($RedirectPath ne $Path) {
6677 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6678 }
6679 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006680 else
6681 { # can't find
6682 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006684 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006685 if(my $Inc = parse_includes($Content, $Path))
6686 {
6687 foreach my $Include (keys(%{$Inc}))
6688 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006689 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006690
6691 if(defined $Tolerance and $Tolerance=~/4/)
6692 {
6693 if(my $HPath = identifyHeader($Include, $LibVersion))
6694 {
6695 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6696 }
6697 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006700}
6701
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006702sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006703{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704 my $Path = $_[0];
6705 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006706 if($OStarget eq "symbian")
6707 {
6708 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6709 { # epoc32/include/libc/{stdio, ...}.h
6710 return 1;
6711 }
6712 }
6713 else
6714 {
6715 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6716 { # /usr/include/{stdio, ...}.h
6717 return 1;
6718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006720 return 0;
6721}
6722
6723sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006724{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 my $Dir = $_[0];
6726 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006727 if($OStarget eq "symbian")
6728 {
6729 if(get_filename($OutDir) eq "libc"
6730 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6731 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6732 return 1;
6733 }
6734 }
6735 else
6736 { # linux
6737 if($OutDir eq "/usr/include"
6738 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6739 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6740 return 1;
6741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 }
6743 return 0;
6744}
6745
6746sub detect_recursive_includes($$)
6747{
6748 my ($AbsPath, $LibVersion) = @_;
6749 return () if(not $AbsPath);
6750 if(isCyclical(\@RecurInclude, $AbsPath)) {
6751 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6752 }
6753 my ($AbsDir, $Name) = separate_path($AbsPath);
6754 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006755 { # system GLIBC internals
6756 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006757 }
6758 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6759 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6760 }
6761 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006762
6763 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6764 { # skip /usr/include/c++/*/ headers
6765 return () if(not $ExtraInfo);
6766 }
6767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006768 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006769 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006770 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006771 { # check "real" (non-"model") include paths
6772 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6773 pop(@RecurInclude);
6774 return @Paths;
6775 }
6776 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6777 detect_header_includes($AbsPath, $LibVersion);
6778 }
6779 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6780 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006781 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006782 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006783 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006784 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006785 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006787 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 }
6789 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006790 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006791 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006792 { # search for the nearest header
6793 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006794 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 if(-f $Candidate) {
6796 $HPath = $Candidate;
6797 }
6798 }
6799 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006800 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006801 }
6802 next if(not $HPath);
6803 if($HPath eq $AbsPath) {
6804 next;
6805 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006806
6807 if($Debug)
6808 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006809# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6810# {
6811# print STDERR "$AbsPath -> $HPath\n";
6812# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006813 }
6814
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006815 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6816 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006817 { # only include <...>, skip include "..." prefixes
6818 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6819 }
6820 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6821 {
6822 if($IncPath eq $AbsPath) {
6823 next;
6824 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006825 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6826 if($RIncType==-1)
6827 { # include "..."
6828 $RIncType = $IncType;
6829 }
6830 elsif($RIncType==2)
6831 {
6832 if($IncType!=-1) {
6833 $RIncType = $IncType;
6834 }
6835 }
6836 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006837 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6838 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6839 }
6840 }
6841 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6842 {
6843 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6844 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6845 { # distinguish math.h from glibc and math.h from the tested library
6846 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6847 last;
6848 }
6849 }
6850 }
6851 pop(@RecurInclude);
6852 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6853}
6854
6855sub find_in_framework($$$)
6856{
6857 my ($Header, $Framework, $LibVersion) = @_;
6858 return "" if(not $Header or not $Framework or not $LibVersion);
6859 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6860 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6861 }
6862 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6863 {
6864 if(get_filename($Dependency) eq $Framework
6865 and -f get_dirname($Dependency)."/".$Header) {
6866 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6867 }
6868 }
6869 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6870}
6871
6872sub find_in_defaults($)
6873{
6874 my $Header = $_[0];
6875 return "" if(not $Header);
6876 if(defined $Cache{"find_in_defaults"}{$Header}) {
6877 return $Cache{"find_in_defaults"}{$Header};
6878 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006879 foreach my $Dir (@DefaultIncPaths,
6880 @DefaultGccPaths,
6881 @DefaultCppPaths,
6882 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006883 {
6884 next if(not $Dir);
6885 if(-f $Dir."/".$Header) {
6886 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6887 }
6888 }
6889 return ($Cache{"find_in_defaults"}{$Header}="");
6890}
6891
6892sub cmp_paths($$)
6893{
6894 my ($Path1, $Path2) = @_;
6895 my @Parts1 = split(/[\/\\]/, $Path1);
6896 my @Parts2 = split(/[\/\\]/, $Path2);
6897 foreach my $Num (0 .. $#Parts1)
6898 {
6899 my $Part1 = $Parts1[$Num];
6900 my $Part2 = $Parts2[$Num];
6901 if($GlibcDir{$Part1}
6902 and not $GlibcDir{$Part2}) {
6903 return 1;
6904 }
6905 elsif($GlibcDir{$Part2}
6906 and not $GlibcDir{$Part1}) {
6907 return -1;
6908 }
6909 elsif($Part1=~/glib/
6910 and $Part2!~/glib/) {
6911 return 1;
6912 }
6913 elsif($Part1!~/glib/
6914 and $Part2=~/glib/) {
6915 return -1;
6916 }
6917 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6918 return $CmpRes;
6919 }
6920 }
6921 return 0;
6922}
6923
6924sub checkRelevance($)
6925{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006926 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006927 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006928
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006929 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006930 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006932
6933 my $Name = lc(get_filename($Path));
6934 my $Dir = lc(get_dirname($Path));
6935
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006936 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006937
6938 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006939 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006940 my $Len = length($Token);
6941 next if($Len<=1);
6942 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6943 { # include/evolution-data-server-1.4/libebook/e-book.h
6944 return 1;
6945 }
6946 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006947 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006948 return 1;
6949 }
6950 }
6951 return 0;
6952}
6953
6954sub checkFamily(@)
6955{
6956 my @Paths = @_;
6957 return 1 if($#Paths<=0);
6958 my %Prefix = ();
6959 foreach my $Path (@Paths)
6960 {
6961 if($SystemRoot) {
6962 $Path = cut_path_prefix($Path, $SystemRoot);
6963 }
6964 if(my $Dir = get_dirname($Path))
6965 {
6966 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6967 $Prefix{$Dir} += 1;
6968 $Prefix{get_dirname($Dir)} += 1;
6969 }
6970 }
6971 foreach (sort keys(%Prefix))
6972 {
6973 if(get_depth($_)>=3
6974 and $Prefix{$_}==$#Paths+1) {
6975 return 1;
6976 }
6977 }
6978 return 0;
6979}
6980
6981sub isAcceptable($$$)
6982{
6983 my ($Header, $Candidate, $LibVersion) = @_;
6984 my $HName = get_filename($Header);
6985 if(get_dirname($Header))
6986 { # with prefix
6987 return 1;
6988 }
6989 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6990 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6991 return 1;
6992 }
6993 if(checkRelevance($Candidate))
6994 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6995 return 1;
6996 }
6997 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6998 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6999 # /usr/include/qt4/Qt/qsslconfiguration.h
7000 return 1;
7001 }
7002 if($OStarget eq "symbian")
7003 {
7004 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7005 return 1;
7006 }
7007 }
7008 return 0;
7009}
7010
7011sub isRelevant($$$)
7012{ # disallow to search for "abstract" headers in too deep directories
7013 my ($Header, $Candidate, $LibVersion) = @_;
7014 my $HName = get_filename($Header);
7015 if($OStarget eq "symbian")
7016 {
7017 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7018 return 0;
7019 }
7020 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007021 if($OStarget ne "bsd")
7022 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007023 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7024 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7025 return 0;
7026 }
7027 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007028 if($OStarget ne "windows")
7029 {
7030 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7031 { # skip /usr/include/wine/msvcrt
7032 return 0;
7033 }
7034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007035 if(not get_dirname($Header)
7036 and $Candidate=~/[\/\\]wx[\/\\]/)
7037 { # do NOT search in system /wx/ directory
7038 # for headers without a prefix: sstream.h
7039 return 0;
7040 }
7041 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7042 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7043 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7044 return 0;
7045 }
7046 if($Candidate=~/[\/\\]asm-/
7047 and (my $Arch = getArch($LibVersion)) ne "unknown")
7048 { # arch-specific header files
7049 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7050 {# skip ../asm-arm/ if using x86 architecture
7051 return 0;
7052 }
7053 }
7054 my @Candidates = getSystemHeaders($HName, $LibVersion);
7055 if($#Candidates==1)
7056 { # unique header
7057 return 1;
7058 }
7059 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7060 if($#SCandidates==1)
7061 { # unique name
7062 return 1;
7063 }
7064 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7065 if(get_depth($Candidate)-$SystemDepth>=5)
7066 { # abstract headers in too deep directories
7067 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7068 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7069 return 0;
7070 }
7071 }
7072 if($Header eq "parser.h"
7073 and $Candidate!~/\/libxml2\//)
7074 { # select parser.h from xml2 library
7075 return 0;
7076 }
7077 if(not get_dirname($Header)
7078 and keys(%{$SystemHeaders{$HName}})>=3)
7079 { # many headers with the same name
7080 # like thread.h included without a prefix
7081 if(not checkFamily(@Candidates)) {
7082 return 0;
7083 }
7084 }
7085 return 1;
7086}
7087
7088sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089{ # cache function
7090 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7091 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7092 }
7093 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7094}
7095
7096sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007097{
7098 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007099 if(-f $Header) {
7100 return $Header;
7101 }
7102 if(is_abs($Header) and not -f $Header)
7103 { # incorrect absolute path
7104 return "";
7105 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007106 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007107 { # too abstract configuration headers
7108 return "";
7109 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007110 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007111 if($OSgroup ne "windows")
7112 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007113 if(defined $WinHeaders{lc($HName)}
7114 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007115 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007116 return "";
7117 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007118 }
7119 if($OSgroup ne "macos")
7120 {
7121 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007122 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007123 return "";
7124 }
7125 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007126
7127 if(defined $ObsoleteHeaders{$HName})
7128 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007129 return "";
7130 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007131 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7132 {
7133 if(defined $AlienHeaders{$HName}
7134 or defined $AlienHeaders{$Header})
7135 { # alien headers from other systems
7136 return "";
7137 }
7138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007140 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007141 { # search in default paths
7142 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007143 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007144 }
7145 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007146 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007147 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007148 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149 }
7150 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7151 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7152 {
7153 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007154 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 }
7156 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007157 # error
7158 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159}
7160
7161sub getSystemHeaders($$)
7162{
7163 my ($Header, $LibVersion) = @_;
7164 my @Candidates = ();
7165 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7166 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007167 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168 next;
7169 }
7170 push(@Candidates, $Candidate);
7171 }
7172 return @Candidates;
7173}
7174
7175sub cut_path_prefix($$)
7176{
7177 my ($Path, $Prefix) = @_;
7178 return $Path if(not $Prefix);
7179 $Prefix=~s/[\/\\]+\Z//;
7180 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7181 return $Path;
7182}
7183
7184sub is_default_include_dir($)
7185{
7186 my $Dir = $_[0];
7187 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007188 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007189}
7190
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007191sub identifyHeader($$)
7192{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007194 if(not $Header) {
7195 return "";
7196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007198 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7199 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007200 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007201 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007202}
7203
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007204sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007205{ # search for header by absolute path, relative path or name
7206 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007207 if(-f $Header)
7208 { # it's relative or absolute path
7209 return get_abs_path($Header);
7210 }
7211 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7212 and my $HeaderDir = find_in_defaults($Header))
7213 { # search for libc headers in the /usr/include
7214 # for non-libc target library before searching
7215 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007216 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 }
7218 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7219 { # search in the target library paths
7220 return $Path;
7221 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007222 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007223 { # search in the internal GCC include paths
7224 return $DefaultGccHeader{$Header};
7225 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007226 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007228 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007230 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231 { # search in the default G++ include paths
7232 return $DefaultCppHeader{$Header};
7233 }
7234 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7235 { # search everywhere in the system
7236 return $AnyPath;
7237 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007238 elsif($OSgroup eq "macos")
7239 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7240 if(my $Dir = get_dirname($Header))
7241 {
7242 my $RelPath = "Headers\/".get_filename($Header);
7243 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007244 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007245 }
7246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007248 # cannot find anything
7249 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250}
7251
7252sub getLocation($)
7253{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007254 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7255 {
7256 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007257 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007260 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007261}
7262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263sub getNameByInfo($)
7264{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007265 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007266 {
7267 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7268 {
7269 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7270 {
7271 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7272 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007273 my $Str = $1;
7274 if($CppMode{$Version}
7275 and $Str=~/\Ac99_(.+)\Z/)
7276 {
7277 if($CppKeywords_A{$1}) {
7278 $Str=$1;
7279 }
7280 }
7281 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007282 }
7283 }
7284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007286 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007287}
7288
7289sub getTreeStr($)
7290{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007291 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007292 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007293 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7294 {
7295 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007296 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007297 and $Str=~/\Ac99_(.+)\Z/)
7298 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007299 if($CppKeywords_A{$1}) {
7300 $Str=$1;
7301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007306 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307}
7308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309sub getFuncShortName($)
7310{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007311 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007313 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007314 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007315 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007316 {
7317 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7318 {
7319 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7320 return "operator ".$RName;
7321 }
7322 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007323 }
7324 else
7325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007326 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7327 {
7328 if(my $Ind = $Operator_Indication{$1}) {
7329 return "operator".$Ind;
7330 }
7331 elsif(not $UnknownOperator{$1})
7332 {
7333 printMsg("WARNING", "unknown operator $1");
7334 $UnknownOperator{$1} = 1;
7335 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007336 }
7337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007338 }
7339 else
7340 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007341 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7342 return getTreeStr($1);
7343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007344 }
7345 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007346 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347}
7348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007349sub getFuncReturn($)
7350{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007351 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7352 {
7353 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7354 {
7355 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7356 return $1;
7357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007358 }
7359 }
7360 return "";
7361}
7362
7363sub getFuncOrig($)
7364{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007365 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7366 {
7367 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7368 return $1;
7369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007370 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007371 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007372}
7373
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374sub unmangleArray(@)
7375{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007376 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007377 { # MSVC mangling
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007378 if(defined $DisabledMSVCUnmangling) {
7379 return @_;
7380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381 my $UndNameCmd = get_CmdPath("undname");
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007382 if(not $UndNameCmd)
7383 {
7384 if($OSgroup eq "windows") {
7385 exitStatus("Not_Found", "can't find \"undname\"");
7386 }
7387 elsif(not defined $DisabledMSVCUnmangling)
7388 {
7389 printMsg("WARNING", "can't find \"undname\", disable MSVC unmangling");
7390 $DisabledMSVCUnmangling = 1;
7391 return @_;
7392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007393 }
7394 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007395 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007396 }
7397 else
7398 { # GCC mangling
7399 my $CppFiltCmd = get_CmdPath("c++filt");
7400 if(not $CppFiltCmd) {
7401 exitStatus("Not_Found", "can't find c++filt in PATH");
7402 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007403 if(not defined $CPPFILT_SUPPORT_FILE)
7404 {
7405 my $Info = `$CppFiltCmd -h 2>&1`;
7406 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7407 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007408 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007409 if($CPPFILT_SUPPORT_FILE)
7410 { # new versions of c++filt can take a file
7411 if($#_>$MAX_CPPFILT_FILE_SIZE)
7412 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7413 # this is fixed in the oncoming version of Binutils
7414 my @Half = splice(@_, 0, ($#_+1)/2);
7415 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007417 else
7418 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007419 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7420 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7421 if($?==139)
7422 { # segmentation fault
7423 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7424 }
7425 return split(/\n/, $Res);
7426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007427 }
7428 else
7429 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007430 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7431 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007432 my @Half = splice(@_, 0, ($#_+1)/2);
7433 return (unmangleArray(@Half), unmangleArray(@_))
7434 }
7435 else
7436 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007437 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007438 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7439 if($?==139)
7440 { # segmentation fault
7441 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7442 }
7443 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 }
7445 }
7446 }
7447}
7448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449sub get_ChargeLevel($$)
7450{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007451 my ($Symbol, $LibVersion) = @_;
7452 return "" if($Symbol!~/\A(_Z|\?)/);
7453 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7454 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007455 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007456 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007458 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007459 return "[in-charge]";
7460 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007461 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 return "[not-in-charge]";
7463 }
7464 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007465 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007467 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 return "[in-charge]";
7469 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007470 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007471 return "[not-in-charge]";
7472 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007473 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007474 return "[in-charge-deleting]";
7475 }
7476 }
7477 }
7478 else
7479 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007480 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 return "[in-charge]";
7482 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007483 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007484 return "[not-in-charge]";
7485 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007486 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487 return "[in-charge]";
7488 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007489 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007490 return "[not-in-charge]";
7491 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007492 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007493 return "[in-charge-deleting]";
7494 }
7495 }
7496 return "";
7497}
7498
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007499sub get_Signature_M($$)
7500{
7501 my ($Symbol, $LibVersion) = @_;
7502 my $Signature_M = $tr_name{$Symbol};
7503 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7504 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007506 }
7507 return $Signature_M;
7508}
7509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007510sub get_Signature($$)
7511{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007512 my ($Symbol, $LibVersion) = @_;
7513 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7514 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007517 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007518
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007519 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007520
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007522 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007523 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7524 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007525 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7526 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007527
7528 if(index($Symbol, "_ZTV")==0) {
7529 return "vtable for $ClassName [data]";
7530 }
7531
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007532 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007533 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7534 $Signature .= "~";
7535 }
7536 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007538 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007539 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007540 }
7541 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007542 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007543 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007544 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7545 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007547 else
7548 {
7549 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
7551 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007552 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007553 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007554 if($Pos eq "") {
7555 next;
7556 }
7557
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007558 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007559 if(not $ParamTypeId) {
7560 next;
7561 }
7562
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007563 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007564 if(not $ParamTypeName) {
7565 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7566 }
7567 foreach my $Typedef (keys(%ChangedTypedef))
7568 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007569 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7570 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007572 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007573 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7574 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007575 if($ParamName eq "this"
7576 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007577 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007578 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007579 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007580 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007581 }
7582 else {
7583 push(@ParamArray, $ParamTypeName);
7584 }
7585 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007586 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7587 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007588 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007589 }
7590 else
7591 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007592 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007594 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007596 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007597 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7598 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007599 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007600 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7602 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007603 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7606 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007607 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007608 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609 }
7610 }
7611 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007612 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007613 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007614 }
7615 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007616 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007617 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007618 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619}
7620
7621sub create_member_decl($$)
7622{
7623 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007624 if($TName=~/\([\*]+\)/)
7625 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007626 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7627 return $TName;
7628 }
7629 else
7630 {
7631 my @ArraySizes = ();
7632 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7633 push(@ArraySizes, $1);
7634 }
7635 return $TName." ".$Member.join("", @ArraySizes);
7636 }
7637}
7638
7639sub getFuncType($)
7640{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007641 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7642 {
7643 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7644 {
7645 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7646 {
7647 if($Type eq "method_type") {
7648 return "Method";
7649 }
7650 elsif($Type eq "function_type") {
7651 return "Function";
7652 }
7653 else {
7654 return "Other";
7655 }
7656 }
7657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007658 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007659 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007660}
7661
7662sub getFuncTypeId($)
7663{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007664 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7665 {
7666 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7667 return $1;
7668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007669 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007670 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007671}
7672
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007674{ # "._N" or "$_N" in older GCC versions
7675 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007676}
7677
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007678sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007679{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007680 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7681 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007682 }
7683
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007684 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007685
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007686 if($_[1] ne "S")
7687 {
7688 $N=~s/\A[ ]+//g;
7689 $N=~s/[ ]+\Z//g;
7690 $N=~s/[ ]{2,}/ /g;
7691 }
7692
7693 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007694
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007695 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7696
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007697 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007698
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007699 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7700 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007701
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007702 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007703
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007704 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007705
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007706 if($_[1] eq "S")
7707 {
7708 if(index($N, "operator")!=-1) {
7709 $N=~s/\b(operator[ ]*)> >/$1>>/;
7710 }
7711 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007712
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007713 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007714
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007715 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007716}
7717
7718sub get_HeaderDeps($$)
7719{
7720 my ($AbsPath, $LibVersion) = @_;
7721 return () if(not $AbsPath or not $LibVersion);
7722 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7723 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7724 }
7725 my %IncDir = ();
7726 detect_recursive_includes($AbsPath, $LibVersion);
7727 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7728 {
7729 next if(not $HeaderPath);
7730 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7731 my $Dir = get_dirname($HeaderPath);
7732 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7733 {
7734 my $Dep = $Dir;
7735 if($Prefix)
7736 {
7737 if($OSgroup eq "windows")
7738 { # case insensitive seach on windows
7739 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7740 next;
7741 }
7742 }
7743 elsif($OSgroup eq "macos")
7744 { # seach in frameworks
7745 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7746 {
7747 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7748 {# frameworks
7749 my ($HFramework, $HName) = ($1, $2);
7750 $Dep = $HFramework;
7751 }
7752 else
7753 {# mismatch
7754 next;
7755 }
7756 }
7757 }
7758 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7759 { # Linux, FreeBSD
7760 next;
7761 }
7762 }
7763 if(not $Dep)
7764 { # nothing to include
7765 next;
7766 }
7767 if(is_default_include_dir($Dep))
7768 { # included by the compiler
7769 next;
7770 }
7771 if(get_depth($Dep)==1)
7772 { # too short
7773 next;
7774 }
7775 if(isLibcDir($Dep))
7776 { # do NOT include /usr/include/{sys,bits}
7777 next;
7778 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007779 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007780 }
7781 }
7782 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7783 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7784}
7785
7786sub sortIncPaths($$)
7787{
7788 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007789 if(not $ArrRef or $#{$ArrRef}<0) {
7790 return $ArrRef;
7791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007792 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7793 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007794 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007795 return $ArrRef;
7796}
7797
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007798sub sortDeps($$$)
7799{
7800 if($Header_Dependency{$_[2]}{$_[0]}
7801 and not $Header_Dependency{$_[2]}{$_[1]}) {
7802 return 1;
7803 }
7804 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7805 and $Header_Dependency{$_[2]}{$_[1]}) {
7806 return -1;
7807 }
7808 return 0;
7809}
7810
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007811sub join_P($$)
7812{
7813 my $S = "/";
7814 if($OSgroup eq "windows") {
7815 $S = "\\";
7816 }
7817 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007818}
7819
7820sub get_namespace_additions($)
7821{
7822 my $NameSpaces = $_[0];
7823 my ($Additions, $AddNameSpaceId) = ("", 1);
7824 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7825 {
7826 next if($SkipNameSpaces{$Version}{$NS});
7827 next if(not $NS or $NameSpaces->{$NS}==-1);
7828 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7829 next if($NS=~/\A__/i);
7830 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007831 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007832 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7833 my @NS_Parts = split(/::/, $NS);
7834 next if($#NS_Parts==-1);
7835 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7836 foreach my $NS_Part (@NS_Parts)
7837 {
7838 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7839 $TypeDecl_Suffix .= "}";
7840 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007841 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007842 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7843 $Additions.=" $TypeDecl\n $FuncDecl\n";
7844 $AddNameSpaceId+=1;
7845 }
7846 return $Additions;
7847}
7848
7849sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007850{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007851 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007852 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007853 if($Fmt eq "windows")
7854 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007855 $Path=~s/\//\\/g;
7856 $Path=lc($Path);
7857 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007858 else
7859 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007860 $Path=~s/\\/\//g;
7861 }
7862 return $Path;
7863}
7864
7865sub inc_opt($$)
7866{
7867 my ($Path, $Style) = @_;
7868 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007869 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007870 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007871 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007872 return "-I\"".path_format($Path, "unix")."\"";
7873 }
7874 elsif($OSgroup eq "macos"
7875 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007876 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007877 return "-F".esc(get_dirname($Path));
7878 }
7879 else {
7880 return "-I".esc($Path);
7881 }
7882 }
7883 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007884 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007885 }
7886 return "";
7887}
7888
7889sub platformSpecs($)
7890{
7891 my $LibVersion = $_[0];
7892 my $Arch = getArch($LibVersion);
7893 if($OStarget eq "symbian")
7894 { # options for GCCE compiler
7895 my %Symbian_Opts = map {$_=>1} (
7896 "-D__GCCE__",
7897 "-DUNICODE",
7898 "-fexceptions",
7899 "-D__SYMBIAN32__",
7900 "-D__MARM_INTERWORK__",
7901 "-D_UNICODE",
7902 "-D__S60_50__",
7903 "-D__S60_3X__",
7904 "-D__SERIES60_3X__",
7905 "-D__EPOC32__",
7906 "-D__MARM__",
7907 "-D__EABI__",
7908 "-D__MARM_ARMV5__",
7909 "-D__SUPPORT_CPP_EXCEPTIONS__",
7910 "-march=armv5t",
7911 "-mapcs",
7912 "-mthumb-interwork",
7913 "-DEKA2",
7914 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7915 );
7916 return join(" ", keys(%Symbian_Opts));
7917 }
7918 elsif($OSgroup eq "windows"
7919 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7920 { # add options to MinGW compiler
7921 # to simulate the MSVC compiler
7922 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007923 "-D__unaligned=\" \"",
7924 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007925 "-D_WIN32",
7926 "-D_STDCALL_SUPPORTED",
7927 "-D__int64=\"long long\"",
7928 "-D__int32=int",
7929 "-D__int16=short",
7930 "-D__int8=char",
7931 "-D__possibly_notnullterminated=\" \"",
7932 "-D__nullterminated=\" \"",
7933 "-D__nullnullterminated=\" \"",
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007934 "-D__assume=\" \"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007935 "-D__w64=\" \"",
7936 "-D__ptr32=\" \"",
7937 "-D__ptr64=\" \"",
7938 "-D__forceinline=inline",
7939 "-D__inline=inline",
7940 "-D__uuidof(x)=IID()",
7941 "-D__try=",
7942 "-D__except(x)=",
7943 "-D__declspec(x)=__attribute__((x))",
7944 "-D__pragma(x)=",
7945 "-D_inline=inline",
7946 "-D__forceinline=__inline",
7947 "-D__stdcall=__attribute__((__stdcall__))",
7948 "-D__cdecl=__attribute__((__cdecl__))",
7949 "-D__fastcall=__attribute__((__fastcall__))",
7950 "-D__thiscall=__attribute__((__thiscall__))",
7951 "-D_stdcall=__attribute__((__stdcall__))",
7952 "-D_cdecl=__attribute__((__cdecl__))",
7953 "-D_fastcall=__attribute__((__fastcall__))",
7954 "-D_thiscall=__attribute__((__thiscall__))",
7955 "-DSHSTDAPI_(x)=x",
7956 "-D_MSC_EXTENSIONS",
7957 "-DSECURITY_WIN32",
7958 "-D_MSC_VER=1500",
7959 "-D_USE_DECLSPECS_FOR_SAL",
7960 "-D__noop=\" \"",
7961 "-DDECLSPEC_DEPRECATED=\" \"",
7962 "-D__builtin_alignof(x)=__alignof__(x)",
7963 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007964 if($Arch eq "x86")
7965 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007966 $MinGW_Opts{"-D_X86_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007967 $MinGW_Opts{"-D_M_IX86=300"}=1;
7968 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007969 elsif($Arch eq "x86_64")
7970 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007971 $MinGW_Opts{"-D_AMD64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007972 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007973 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007974 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007975 elsif($Arch eq "ia64")
7976 {
7977 $MinGW_Opts{"-D_IA64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978 $MinGW_Opts{"-D_M_IA64=300"}=1;
7979 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007980 return join(" ", sort keys(%MinGW_Opts));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 }
7982 return "";
7983}
7984
7985my %C_Structure = map {$_=>1} (
7986# FIXME: Can't separate union and struct data types before dumping,
7987# so it sometimes cause compilation errors for unknown reason
7988# when trying to declare TYPE* tmp_add_class_N
7989# This is a list of such structures + list of other C structures
7990 "sigval",
7991 "sigevent",
7992 "sigaction",
7993 "sigvec",
7994 "sigstack",
7995 "timeval",
7996 "timezone",
7997 "rusage",
7998 "rlimit",
7999 "wait",
8000 "flock",
8001 "stat",
8002 "_stat",
8003 "stat32",
8004 "_stat32",
8005 "stat64",
8006 "_stat64",
8007 "_stati64",
8008 "if_nameindex",
8009 "usb_device",
8010 "sigaltstack",
8011 "sysinfo",
8012 "timeLocale",
8013 "tcp_debug",
8014 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008015 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008016 "timespec",
8017 "random_data",
8018 "drand48_data",
8019 "_IO_marker",
8020 "_IO_FILE",
8021 "lconv",
8022 "sched_param",
8023 "tm",
8024 "itimerspec",
8025 "_pthread_cleanup_buffer",
8026 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008027 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008028 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008029 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008030 "sigcontext",
8031 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008032 # Mac
8033 "_timex",
8034 "_class_t",
8035 "_category_t",
8036 "_class_ro_t",
8037 "_protocol_t",
8038 "_message_ref_t",
8039 "_super_message_ref_t",
8040 "_ivar_t",
8041 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008042);
8043
8044sub getCompileCmd($$$)
8045{
8046 my ($Path, $Opt, $Inc) = @_;
8047 my $GccCall = $GCC_PATH;
8048 if($Opt) {
8049 $GccCall .= " ".$Opt;
8050 }
8051 $GccCall .= " -x ";
8052 if($OSgroup eq "macos") {
8053 $GccCall .= "objective-";
8054 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008055
8056 if($EMERGENCY_MODE_48)
8057 { # workaround for GCC 4.8 (C only)
8058 $GccCall .= "c++";
8059 }
8060 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008061 { # compile as "C++" header
8062 # to obtain complete dump using GCC 4.0
8063 $GccCall .= "c++-header";
8064 }
8065 else
8066 { # compile as "C++" source
8067 # GCC 3.3 cannot compile headers
8068 $GccCall .= "c++";
8069 }
8070 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008071 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008072 $GccCall .= " ".$Opts;
8073 }
8074 # allow extra qualifications
8075 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008076 $GccCall .= " -fpermissive";
8077 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008078 if($NoStdInc)
8079 {
8080 $GccCall .= " -nostdinc";
8081 $GccCall .= " -nostdinc++";
8082 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008083 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008084 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008085 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008086 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008087 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008088 if($Inc)
8089 { # include paths
8090 $GccCall .= " ".$Inc;
8091 }
8092 return $GccCall;
8093}
8094
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008095sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008096{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008097 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008098 my %HeaderElems = (
8099 # Types
8100 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008101 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008102 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8103 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008104 "time.h" => ["time_t"],
8105 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008106 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8107 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008108 "stdbool.h" => ["_Bool"],
8109 "rpc/xdr.h" => ["bool_t"],
8110 "in_systm.h" => ["n_long", "n_short"],
8111 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008112 "arpa/inet.h" => ["fw_src", "ip_src"],
8113 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008114 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008115 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008116 );
8117 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008118 foreach (keys(%HeaderElems))
8119 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008121 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008122 }
8123 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008124 my %Types = ();
8125 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8126 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008127 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008128 }
8129 if(keys(%Types))
8130 {
8131 my %AddHeaders = ();
8132 foreach my $Type (keys(%Types))
8133 {
8134 if(my $Header = $AutoPreamble{$Type})
8135 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008136 if(my $Path = identifyHeader($Header, $LibVersion))
8137 {
8138 if(skipHeader($Path, $LibVersion)) {
8139 next;
8140 }
8141 $Path = path_format($Path, $OSgroup);
8142 $AddHeaders{$Path}{"Type"} = $Type;
8143 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008144 }
8145 }
8146 }
8147 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008148 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008149 }
8150 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008151 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008152}
8153
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008154sub checkCTags($)
8155{
8156 my $Path = $_[0];
8157 if(not $Path) {
8158 return;
8159 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008160 my $CTags = undef;
8161
8162 if($OSgroup eq "bsd")
8163 { # use ectags on BSD
8164 $CTags = get_CmdPath("ectags");
8165 if(not $CTags) {
8166 printMsg("WARNING", "can't find \'ectags\' program");
8167 }
8168 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008169 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008170 $CTags = get_CmdPath("ctags");
8171 }
8172 if(not $CTags)
8173 {
8174 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008175 return;
8176 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008177
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008178 if($OSgroup ne "linux")
8179 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008180 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkodd172162016-10-04 19:41:25 +03008181 if($Info!~/universal|exuberant/i)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008182 {
8183 printMsg("WARNING", "incompatible version of \'ctags\' program");
8184 return;
8185 }
8186 }
8187
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008188 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008189 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008190 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008191 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008192 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008193 open(CTAGS, "<", $Out);
8194 while(my $Line = <CTAGS>)
8195 {
8196 chomp($Line);
8197 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008198 if(defined $Intrinsic_Keywords{$Name})
8199 { # noise
8200 next;
8201 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008202 if($Type eq "n")
8203 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008204 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008205 next;
8206 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008207 if(index($Scpe, "struct:")==0) {
8208 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008210 if(index($Scpe, "namespace:")==0)
8211 {
8212 if($Scpe=~s/\Anamespace://) {
8213 $Name = $Scpe."::".$Name;
8214 }
8215 }
8216 $TUnit_NameSpaces{$Version}{$Name} = 1;
8217 }
8218 elsif($Type eq "p")
8219 {
8220 if(not $Scpe or index($Scpe, "namespace:")==0) {
8221 $TUnit_Funcs{$Version}{$Name} = 1;
8222 }
8223 }
8224 elsif($Type eq "x")
8225 {
8226 if(not $Scpe or index($Scpe, "namespace:")==0) {
8227 $TUnit_Vars{$Version}{$Name} = 1;
8228 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008229 }
8230 }
8231 close(CTAGS);
8232}
8233
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008234sub preChange($$)
8235{
8236 my ($HeaderPath, $IncStr) = @_;
8237
8238 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8239 my $Content = undef;
8240
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008241 if(not defined $MinGWCompat and $OStarget eq "windows"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008242 and get_dumpmachine($GCC_PATH)=~/mingw/i
8243 and $MinGWMode{$Version}!=-1)
8244 { # modify headers to compile by MinGW
8245 if(not $Content)
8246 { # preprocessing
8247 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8248 }
8249 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8250 { # __asm { ... }
8251 $MinGWMode{$Version}=1;
8252 }
8253 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8254 { # comments after preprocessing
8255 $MinGWMode{$Version}=1;
8256 }
8257 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8258 { # 0xffui8
8259 $MinGWMode{$Version}=1;
8260 }
8261
8262 if($MinGWMode{$Version}) {
8263 printMsg("INFO", "Using MinGW compatibility mode");
8264 }
8265 }
8266
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008267 if(defined $CxxIncompat and ($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8268 and $CppMode{$Version}!=-1 and not $CPP_HEADERS)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008269 { # rename C++ keywords in C code
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008270 printMsg("INFO", "Checking the code for C++ keywords");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008271 if(not $Content)
8272 { # preprocessing
8273 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8274 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008275
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008276 my $RegExp_C = join("|", keys(%CppKeywords_C));
8277 my $RegExp_F = join("|", keys(%CppKeywords_F));
8278 my $RegExp_O = join("|", keys(%CppKeywords_O));
8279
8280 my $Detected = undef;
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008281 my $Sentence_O = undef;
8282 my $Sentence_N = undef;
8283 my $Regex = undef;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008284
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008285 $Regex = qr/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/;
8286 while($Content=~/$Regex/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008287 { # MATCH:
8288 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008289 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008290 # unsigned private: 8;
8291 # DO NOT MATCH:
8292 # #pragma GCC visibility push(default)
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008293 $Sentence_O = "$1$2$3$4";
8294 $Sentence_N = "$1$2c99_$3$4";
8295
8296 if($Sentence_O=~/\s+decltype\(/)
8297 { # C++
8298 # decltype(nullptr)
8299 last;
8300 }
8301 else
8302 {
8303 $Content=~s/$Regex/$Sentence_N/g;
8304 $CppMode{$Version} = 1;
8305 if(not defined $Detected) {
8306 $Detected = $Sentence_O;
8307 }
8308 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008309 }
8310 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8311 { # MATCH:
8312 # int delete(...);
8313 # int explicit(...);
8314 # DO NOT MATCH:
8315 # void operator delete(...)
8316 $CppMode{$Version} = 1;
8317 $Detected = "$1$2$3" if(not defined $Detected);
8318 }
8319 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8320 { # MATCH:
8321 # int bool;
8322 # DO NOT MATCH:
8323 # bool X;
8324 # return *this;
8325 # throw;
8326 $CppMode{$Version} = 1;
8327 $Detected = "$1$2$3" if(not defined $Detected);
8328 }
8329 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8330 { # MATCH:
8331 # int operator(...);
8332 # DO NOT MATCH:
8333 # int operator()(...);
8334 $CppMode{$Version} = 1;
8335 $Detected = "$1$2$3" if(not defined $Detected);
8336 }
8337 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8338 { # MATCH:
8339 # int foo(int operator);
8340 # int foo(int operator, int other);
8341 # DO NOT MATCH:
8342 # int operator,(...);
8343 $CppMode{$Version} = 1;
8344 $Detected = "$1$2$3" if(not defined $Detected);
8345 }
8346 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8347 { # MATCH:
8348 # int foo(gboolean *bool);
8349 # DO NOT MATCH:
8350 # void setTabEnabled(int index, bool);
8351 $CppMode{$Version} = 1;
8352 $Detected = "$1$2$3" if(not defined $Detected);
8353 }
8354 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8355 { # MATCH:
8356 # int foo(int* this);
8357 # int bar(int this);
8358 # int baz(int throw);
8359 # DO NOT MATCH:
8360 # foo(X, this);
8361 $CppMode{$Version} = 1;
8362 $Detected = "$1$2$3$4" if(not defined $Detected);
8363 }
8364 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8365 { # MATCH:
8366 # struct template {...};
8367 # extern template foo(...);
8368 $CppMode{$Version} = 1;
8369 $Detected = "$1$2" if(not defined $Detected);
8370 }
8371
8372 if($CppMode{$Version} == 1)
8373 {
8374 if($Debug)
8375 {
8376 $Detected=~s/\A\s+//g;
8377 printMsg("INFO", "Detected code: \"$Detected\"");
8378 }
8379 }
8380
8381 # remove typedef enum NAME NAME;
8382 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8383 my $N = 0;
8384 while($N<=$#FwdTypedefs-1)
8385 {
8386 my $S = $FwdTypedefs[$N];
8387 if($S eq $FwdTypedefs[$N+1])
8388 {
8389 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008390 $CppMode{$Version} = 1;
8391
8392 if($Debug) {
8393 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8394 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008395 }
8396 $N+=2;
8397 }
8398
8399 if($CppMode{$Version}==1) {
8400 printMsg("INFO", "Using C++ compatibility mode");
8401 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008402 else {
8403 printMsg("INFO", "C++ keywords in the C code are not found");
8404 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008405 }
8406
8407 if($CppMode{$Version}==1
8408 or $MinGWMode{$Version}==1)
8409 {
8410 my $IPath = $TMP_DIR."/dump$Version.i";
8411 writeFile($IPath, $Content);
8412 return $IPath;
8413 }
8414
8415 return undef;
8416}
8417
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008418sub getDump()
8419{
8420 if(not $GCC_PATH) {
8421 exitStatus("Error", "internal error - GCC path is not set");
8422 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008423
8424 my @Headers = keys(%{$Registered_Headers{$Version}});
8425 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8426
8427 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8428
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008429 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008430 my $HeaderPath = $TmpHeaderPath;
8431
8432 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008433 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008434 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8435 {
8436 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008437 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008439 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008440 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8441 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008442 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008443 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008444 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008445 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8446 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008449 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008450
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008451 if($ExtraInfo)
8452 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008453 if($IncludeString) {
8454 writeFile($ExtraInfo."/include-string", $IncludeString);
8455 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008456 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8457 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008458
8459 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8460 {
8461 my $REDIR = "";
8462 foreach my $P1 (sort @Redirects) {
8463 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8464 }
8465 writeFile($ExtraInfo."/include-redirect", $REDIR);
8466 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008467 }
8468
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008469 if(not keys(%{$TargetHeaders{$Version}}))
8470 { # Target headers
8471 addTargetHeaders($Version);
8472 }
8473
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008474 # clean memory
8475 %RecursiveIncludes = ();
8476 %Header_Include_Prefix = ();
8477 %Header_Includes = ();
8478
8479 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008480 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008481 delete($Cache{"detect_header_includes"});
8482 delete($Cache{"selectSystemHeader"});
8483
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008484 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008485 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8486 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008487
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008488 if($ExtraInfo)
8489 { # extra information for other tools
8490 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8491 }
8492
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008493 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008494 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008495 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008496
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008497 if($COMMON_LANGUAGE{$Version} eq "C++") {
8498 checkCTags($Pre);
8499 }
8500
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008501 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8502 { # try to correct the preprocessor output
8503 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008504 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008506 if($COMMON_LANGUAGE{$Version} eq "C++")
8507 { # add classes and namespaces to the dump
8508 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008509 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 or $MinGWMode{$Version}==1) {
8511 $CHdump .= " -fpreprocessed";
8512 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008513 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008514 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008515 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008516 chdir($ORIG_DIR);
8517 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8518 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008519 my $Content = readFile($ClassDump);
8520 foreach my $ClassInfo (split(/\n\n/, $Content))
8521 {
8522 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8523 {
8524 my $CName = $1;
8525 next if($CName=~/\A(__|_objc_|_opaque_)/);
8526 $TUnit_NameSpaces{$Version}{$CName} = -1;
8527 if($CName=~/\A[\w:]+\Z/)
8528 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008529 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008530 }
8531 if($CName=~/(\w[\w:]*)::/)
8532 { # namespaces
8533 my $NS = $1;
8534 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8535 $TUnit_NameSpaces{$Version}{$NS} = 1;
8536 }
8537 }
8538 }
8539 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8540 { # read v-tables (advanced approach)
8541 my ($CName, $VTable) = ($1, $2);
8542 $ClassVTable_Content{$Version}{$CName} = $VTable;
8543 }
8544 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008545 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8546 { # add user-defined namespaces
8547 $TUnit_NameSpaces{$Version}{$NS} = 1;
8548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008549 if($Debug)
8550 { # debug mode
8551 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008552 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008553 }
8554 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008555 }
8556
8557 # add namespaces and classes
8558 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8559 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008560 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008561 }
8562 # some GCC versions don't include class methods to the TU dump by default
8563 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008564 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008565 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8566 {
8567 next if($C_Structure{$CName});
8568 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008569 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008570 if(not $Force and $GCC_44
8571 and $OSgroup eq "linux")
8572 { # optimization for linux with GCC >= 4.4
8573 # disable this code by -force option
8574 if(index($CName, "::")!=-1)
8575 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008576 next;
8577 }
8578 }
8579 else
8580 {
8581 if($CName=~/\A(.+)::[^:]+\Z/
8582 and $TUnit_Classes{$Version}{$1})
8583 { # classes inside other classes
8584 next;
8585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008586 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008587 if(defined $TUnit_Funcs{$Version}{$CName})
8588 { # the same name for a function and type
8589 next;
8590 }
8591 if(defined $TUnit_Vars{$Version}{$CName})
8592 { # the same name for a variable and type
8593 next;
8594 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008595 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8596 }
8597 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008598 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008599 }
8600 }
8601 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8602 # create TU dump
8603 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008604 if($UserLang eq "C") {
8605 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8606 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008607 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608 or $MinGWMode{$Version}==1) {
8609 $TUdump .= " -fpreprocessed";
8610 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008611 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008612 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8613 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008614 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008615 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008616 if($?)
8617 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008618 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008619 { # try to recompile
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008620 # FIXME: handle errors and try to recompile
8621 if($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008622 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008623 { # add auto preamble headers and try again
8624 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008625 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008626 foreach my $Num (0 .. $#Headers)
8627 {
8628 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008629 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8630 {
8631 push_U($Include_Preamble{$Version}, $Path);
8632 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008633 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008634 }
8635 resetLogging($Version);
8636 $TMP_DIR = tempdir(CLEANUP=>1);
8637 return getDump();
8638 }
8639 elsif($Cpp0xMode{$Version}!=-1
8640 and ($Errors=~/\Q-std=c++0x\E/
8641 or $Errors=~/is not a class or namespace/))
8642 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008643 if(check_gcc($GCC_PATH, "4.6"))
8644 {
8645 $Cpp0xMode{$Version}=-1;
8646 printMsg("INFO", "Enabling c++0x mode");
8647 resetLogging($Version);
8648 $TMP_DIR = tempdir(CLEANUP=>1);
8649 $CompilerOptions{$Version} .= " -std=c++0x";
8650 return getDump();
8651 }
8652 else {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008653 printMsg("WARNING", "Probably c++0x element detected");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008654 }
8655
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008656 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008657 #elsif($MinGWMode{$Version}==1)
8658 #{ # disable MinGW mode and try again
8659 # $MinGWMode{$Version}=-1;
8660 # resetLogging($Version);
8661 # $TMP_DIR = tempdir(CLEANUP=>1);
8662 # return getDump();
8663 #}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008664 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008666 else {
8667 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008669 printMsg("ERROR", "some errors occurred when compiling headers");
8670 printErrorLog($Version);
8671 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008672 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 }
8674 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008675 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008676 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008677
8678 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8679 return $TUs[0];
8680 }
8681 else
8682 {
8683 my $Msg = "can't compile header(s)";
8684 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8685 $Msg .= "\nDid you install G++?";
8686 }
8687 exitStatus("Cannot_Compile", $Msg);
8688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008689}
8690
8691sub cmd_file($)
8692{
8693 my $Path = $_[0];
8694 return "" if(not $Path or not -e $Path);
8695 if(my $CmdPath = get_CmdPath("file")) {
8696 return `$CmdPath -b \"$Path\"`;
8697 }
8698 return "";
8699}
8700
8701sub getIncString($$)
8702{
8703 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008704 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008705 my $String = "";
8706 foreach (@{$ArrRef}) {
8707 $String .= " ".inc_opt($_, $Style);
8708 }
8709 return $String;
8710}
8711
8712sub getIncPaths(@)
8713{
8714 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008715 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008716 if($INC_PATH_AUTODETECT{$Version})
8717 { # auto-detecting dependencies
8718 my %Includes = ();
8719 foreach my $HPath (@HeaderPaths)
8720 {
8721 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8722 {
8723 if($Skip_Include_Paths{$Version}{$Dir}) {
8724 next;
8725 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008726 if($SystemRoot)
8727 {
8728 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8729 next;
8730 }
8731 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008732 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008733 }
8734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008736 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008737 }
8738 }
8739 else
8740 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008741 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008742 }
8743 return \@IncPaths;
8744}
8745
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008746sub push_U($@)
8747{ # push unique
8748 if(my $Array = shift @_)
8749 {
8750 if(@_)
8751 {
8752 my %Exist = map {$_=>1} @{$Array};
8753 foreach my $Elem (@_)
8754 {
8755 if(not defined $Exist{$Elem})
8756 {
8757 push(@{$Array}, $Elem);
8758 $Exist{$Elem} = 1;
8759 }
8760 }
8761 }
8762 }
8763}
8764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008765sub callPreprocessor($$$)
8766{
8767 my ($Path, $Inc, $LibVersion) = @_;
8768 return "" if(not $Path or not -f $Path);
8769 my $IncludeString=$Inc;
8770 if(not $Inc) {
8771 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8772 }
8773 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008774 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008775 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008776 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777}
8778
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008779sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008780{ # native "find" is much faster than File::Find (~6x)
8781 # also the File::Find doesn't support --maxdepth N option
8782 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008783 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 return () if(not $Path or not -e $Path);
8785 if($OSgroup eq "windows")
8786 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008787 $Path = get_abs_path($Path);
8788 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008789 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008790 if($MaxDepth!=1) {
8791 $Cmd .= " /S";
8792 }
8793 if($Type eq "d") {
8794 $Cmd .= " /AD";
8795 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008796 elsif($Type eq "f") {
8797 $Cmd .= " /A-D";
8798 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008799 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008801 {
8802 if(not $UseRegex)
8803 { # FIXME: how to search file names in MS shell?
8804 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008805 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008806 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008807 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008808 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 }
8810 my @AbsPaths = ();
8811 foreach my $File (@Files)
8812 {
8813 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008814 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008815 }
8816 if($Type eq "f" and not -f $File)
8817 { # skip dirs
8818 next;
8819 }
8820 push(@AbsPaths, path_format($File, $OSgroup));
8821 }
8822 if($Type eq "d") {
8823 push(@AbsPaths, $Path);
8824 }
8825 return @AbsPaths;
8826 }
8827 else
8828 {
8829 my $FindCmd = get_CmdPath("find");
8830 if(not $FindCmd) {
8831 exitStatus("Not_Found", "can't find a \"find\" command");
8832 }
8833 $Path = get_abs_path($Path);
8834 if(-d $Path and -l $Path
8835 and $Path!~/\/\Z/)
8836 { # for directories that are symlinks
8837 $Path.="/";
8838 }
8839 my $Cmd = $FindCmd." \"$Path\"";
8840 if($MaxDepth) {
8841 $Cmd .= " -maxdepth $MaxDepth";
8842 }
8843 if($Type) {
8844 $Cmd .= " -type $Type";
8845 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008846 if($Name and not $UseRegex)
8847 { # wildcards
8848 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008849 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008850 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008851 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008852 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8853 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008854 my @Files = split(/\n/, $Res);
8855 if($Name and $UseRegex)
8856 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008857 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008858 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008859 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860 }
8861}
8862
8863sub unpackDump($)
8864{
8865 my $Path = $_[0];
8866 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008868 $Path = get_abs_path($Path);
8869 $Path = path_format($Path, $OSgroup);
8870 my ($Dir, $FileName) = separate_path($Path);
8871 my $UnpackDir = $TMP_DIR."/unpack";
8872 rmtree($UnpackDir);
8873 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008874
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875 if($FileName=~s/\Q.zip\E\Z//g)
8876 { # *.zip
8877 my $UnzipCmd = get_CmdPath("unzip");
8878 if(not $UnzipCmd) {
8879 exitStatus("Not_Found", "can't find \"unzip\" command");
8880 }
8881 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008882 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008883 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008884 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008885 }
8886 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008887 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008888 if(not @Contents) {
8889 exitStatus("Error", "can't extract \'$Path\'");
8890 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008891 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008893 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008894 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008895 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 if($OSgroup eq "windows")
8897 { # -xvzf option is not implemented in tar.exe (2003)
8898 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8899 my $TarCmd = get_CmdPath("tar");
8900 if(not $TarCmd) {
8901 exitStatus("Not_Found", "can't find \"tar\" command");
8902 }
8903 my $GzipCmd = get_CmdPath("gzip");
8904 if(not $GzipCmd) {
8905 exitStatus("Not_Found", "can't find \"gzip\" command");
8906 }
8907 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008908 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 if($?) {
8910 exitStatus("Error", "can't extract \'$Path\'");
8911 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008912 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008914 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 }
8916 chdir($ORIG_DIR);
8917 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008918 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008919 if(not @Contents) {
8920 exitStatus("Error", "can't extract \'$Path\'");
8921 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008922 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008923 }
8924 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008925 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008926 my $TarCmd = get_CmdPath("tar");
8927 if(not $TarCmd) {
8928 exitStatus("Not_Found", "can't find \"tar\" command");
8929 }
8930 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008931 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008932 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008933 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008934 }
8935 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008936 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008937 if(not @Contents) {
8938 exitStatus("Error", "can't extract \'$Path\'");
8939 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008940 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008941 }
8942 }
8943}
8944
8945sub createArchive($$)
8946{
8947 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008948 if(not $To) {
8949 $To = ".";
8950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008951 if(not $Path or not -e $Path
8952 or not -d $To) {
8953 return "";
8954 }
8955 my ($From, $Name) = separate_path($Path);
8956 if($OSgroup eq "windows")
8957 { # *.zip
8958 my $ZipCmd = get_CmdPath("zip");
8959 if(not $ZipCmd) {
8960 exitStatus("Not_Found", "can't find \"zip\"");
8961 }
8962 my $Pkg = $To."/".$Name.".zip";
8963 unlink($Pkg);
8964 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008965 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008966 if($?)
8967 { # cannot allocate memory (or other problems with "zip")
8968 unlink($Path);
8969 exitStatus("Error", "can't pack the ABI dump: ".$!);
8970 }
8971 chdir($ORIG_DIR);
8972 unlink($Path);
8973 return $Pkg;
8974 }
8975 else
8976 { # *.tar.gz
8977 my $TarCmd = get_CmdPath("tar");
8978 if(not $TarCmd) {
8979 exitStatus("Not_Found", "can't find \"tar\"");
8980 }
8981 my $GzipCmd = get_CmdPath("gzip");
8982 if(not $GzipCmd) {
8983 exitStatus("Not_Found", "can't find \"gzip\"");
8984 }
8985 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8986 unlink($Pkg);
8987 chdir($From);
8988 system($TarCmd, "-czf", $Pkg, $Name);
8989 if($?)
8990 { # cannot allocate memory (or other problems with "tar")
8991 unlink($Path);
8992 exitStatus("Error", "can't pack the ABI dump: ".$!);
8993 }
8994 chdir($ORIG_DIR);
8995 unlink($Path);
8996 return $To."/".$Name.".tar.gz";
8997 }
8998}
8999
9000sub is_header_file($)
9001{
9002 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9003 return $_[0];
9004 }
9005 return 0;
9006}
9007
9008sub is_not_header($)
9009{
9010 if($_[0]=~/\.\w+\Z/
9011 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9012 return 1;
9013 }
9014 return 0;
9015}
9016
9017sub is_header($$$)
9018{
9019 my ($Header, $UserDefined, $LibVersion) = @_;
9020 return 0 if(-d $Header);
9021 if(-f $Header) {
9022 $Header = get_abs_path($Header);
9023 }
9024 else
9025 {
9026 if(is_abs($Header))
9027 { # incorrect absolute path
9028 return 0;
9029 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009030 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009031 $Header = $HPath;
9032 }
9033 else
9034 { # can't find header
9035 return 0;
9036 }
9037 }
9038 if($Header=~/\.\w+\Z/)
9039 { # have an extension
9040 return is_header_file($Header);
9041 }
9042 else
9043 {
9044 if($UserDefined==2)
9045 { # specified on the command line
9046 if(cmd_file($Header)!~/HTML|XML/i) {
9047 return $Header;
9048 }
9049 }
9050 elsif($UserDefined)
9051 { # specified in the XML-descriptor
9052 # header file without an extension
9053 return $Header;
9054 }
9055 else
9056 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009057 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009058 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009059 { # !~/HTML|XML|shared|dynamic/i
9060 return $Header;
9061 }
9062 }
9063 }
9064 return 0;
9065}
9066
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009067sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009068{
9069 my $LibVersion = $_[0];
9070 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9071 {
9072 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009073 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009074
9075 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9076 detect_recursive_includes($RegHeader, $LibVersion);
9077 }
9078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009079 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9080 {
9081 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009082
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009083 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009084 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9085 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009086 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009087 }
9088 }
9089 }
9090}
9091
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009092sub familiarDirs($$)
9093{
9094 my ($D1, $D2) = @_;
9095 if($D1 eq $D2) {
9096 return 1;
9097 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009098
9099 my $U1 = index($D1, "/usr/");
9100 my $U2 = index($D2, "/usr/");
9101
9102 if($U1==0 and $U2!=0) {
9103 return 0;
9104 }
9105
9106 if($U2==0 and $U1!=0) {
9107 return 0;
9108 }
9109
9110 if(index($D2, $D1."/")==0) {
9111 return 1;
9112 }
9113
9114 # /usr/include/DIR
9115 # /home/user/DIR
9116
9117 my $DL = get_depth($D1);
9118
9119 my @Dirs1 = ($D1);
9120 while($DL - get_depth($D1)<=2
9121 and get_depth($D1)>=4
9122 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9123 push(@Dirs1, $D1);
9124 }
9125
9126 my @Dirs2 = ($D2);
9127 while(get_depth($D2)>=4
9128 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9129 push(@Dirs2, $D2);
9130 }
9131
9132 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009133 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009134 foreach my $P2 (@Dirs2)
9135 {
9136
9137 if($P1 eq $P2) {
9138 return 1;
9139 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009140 }
9141 }
9142 return 0;
9143}
9144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009145sub readHeaders($)
9146{
9147 $Version = $_[0];
9148 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9149 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009150 if($Debug)
9151 { # debug mode
9152 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009153 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 }
9155 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009156}
9157
9158sub prepareTypes($)
9159{
9160 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009161 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009162 { # support for old ABI dumps
9163 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009164 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009166 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9167 if($TName=~/\A(\w+)::(\w+)/) {
9168 my ($P1, $P2) = ($1, $2);
9169 if($P1 eq $P2) {
9170 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009172 else {
9173 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009176 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009177 }
9178 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009179 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009180 { # support for old ABI dumps
9181 # V < 2.5: array size == "number of elements"
9182 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009183 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009184 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009185 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009186 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009187 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009188 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009189 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009190 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009191 $Size *= $Base{"Size"};
9192 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009193 }
9194 else
9195 { # array[] is a pointer
9196 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009197 }
9198 }
9199 }
9200 }
9201 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009202 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009203 { # support for old ABI dumps
9204 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009205 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009206 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009207 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009208 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009209 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009210 my %Type = get_Type($TypeId, $LibVersion);
9211 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9212 my %Type2 = get_Type($TypeId_2, $V2);
9213 if($Type{"Size"} ne $Type2{"Size"}) {
9214 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009215 }
9216 }
9217 }
9218 }
9219}
9220
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009221sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009222{
9223 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009224
9225 if(not keys(%{$SymbolInfo{$LibVersion}}))
9226 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009227 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228 {
9229 if($CheckHeadersOnly) {
9230 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9231 }
9232 else {
9233 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9234 }
9235 }
9236 }
9237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009238 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009239 if(not checkDump(1, "2.10")
9240 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009241 { # different formats
9242 $Remangle = 1;
9243 }
9244 if($CheckHeadersOnly)
9245 { # different languages
9246 if($UserLang)
9247 { # --lang=LANG for both versions
9248 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9249 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9250 {
9251 if($UserLang eq "C++")
9252 { # remangle symbols
9253 $Remangle = 1;
9254 }
9255 elsif($UserLang eq "C")
9256 { # remove mangling
9257 $Remangle = -1;
9258 }
9259 }
9260 }
9261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009262
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009263 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009264 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009265 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009266 { # support for old ABI dumps
9267 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9268 {
9269 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9270 {
9271 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9272 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009273 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009274 if(defined $DVal and $DVal ne "")
9275 {
9276 if($TName eq "char") {
9277 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9278 }
9279 elsif($TName eq "bool") {
9280 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9281 }
9282 }
9283 }
9284 }
9285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009286 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009287 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009288 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9289 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009290 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9292 # + support for old ABI dumps
9293 next;
9294 }
9295 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009296 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009297 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009298 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009299 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009300
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009301 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009302 if(not checkDump(1, "2.12")
9303 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009304 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009305 if($ShortName eq "operator>>")
9306 {
9307 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9308 { # corrected mangling of operator>>
9309 $SRemangle = 1;
9310 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009312 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9313 {
9314 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9315 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9316 { # corrected mangling of const global data
9317 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9318 # and incorrectly mangled by old ACC versions
9319 $SRemangle = 1;
9320 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009321 }
9322 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009323 if(not $CheckHeadersOnly)
9324 { # support for old ABI dumps
9325 if(not checkDump(1, "2.17")
9326 or not checkDump(2, "2.17"))
9327 {
9328 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9329 {
9330 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9331 {
9332 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9333 {
9334 $MnglName = $ShortName;
9335 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9336 }
9337 }
9338 }
9339 }
9340 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009341 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009342 { # support for old ABI dumps: some symbols are not mangled in old dumps
9343 # mangle both sets of symbols (old and new)
9344 # NOTE: remangling all symbols by the same mangler
9345 if($MnglName=~/\A_ZN(V|)K/)
9346 { # mangling may be incorrect on old ABI dumps
9347 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009348 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009349 }
9350 if($MnglName=~/\A_ZN(K|)V/)
9351 { # mangling may be incorrect on old ABI dumps
9352 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009353 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009354 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009355 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9356 or (not $ClassID and $CheckHeadersOnly)
9357 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9358 { # support for old ABI dumps, GCC >= 4.0
9359 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009360 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009362 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009363 $MangledNames{$LibVersion}{$MnglName} = 1;
9364 }
9365 }
9366 }
9367 elsif($Remangle==-1)
9368 { # remove mangling
9369 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009370 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009372 if(not $MnglName) {
9373 next;
9374 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009375
9376 # NOTE: duplicated entries in the ABI Dump
9377 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9378 {
9379 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9380 {
9381 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9382 {
9383 next;
9384 }
9385 }
9386 }
9387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009388 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9389 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009390 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009393 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 { # support for old dumps
9395 # add "Volatile" attribute
9396 if($MnglName=~/_Z(K|)V/) {
9397 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9398 }
9399 }
9400 # symbol and its symlink have same signatures
9401 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009402 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009403 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009404
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009405 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9406 {
9407 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009408
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009409 if($SymVer{$LibVersion}{$Alias}) {
9410 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9411 }
9412 }
9413
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009414 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009415 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 }
9417 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9418 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9419 }
9420 if($ExtendedCheck)
9421 { # --ext option
9422 addExtension($LibVersion);
9423 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009424
9425 # clean memory
9426 delete($SymbolInfo{$LibVersion});
9427
9428 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 { # detect allocable classes with public exported constructors
9430 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009431 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009432 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009434 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009435 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9436 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009438 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009439 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009440 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 $AllocableClass{$LibVersion}{$ClassName} = 1;
9442 }
9443 }
9444 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009445 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009447 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009448 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009449 if($CheckHeadersOnly)
9450 {
9451 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9452 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9453 { # all symbols except non-virtual inline
9454 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9455 }
9456 }
9457 else {
9458 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 }
9460 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009461 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009462 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 }
9464 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009465 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009467 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009469 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009470 if(defined $Base{"Type"}
9471 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009473 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009474 if($Name=~/<([^<>\s]+)>/)
9475 {
9476 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9477 $ReturnedClass{$LibVersion}{$Tid} = 1;
9478 }
9479 }
9480 else {
9481 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9482 }
9483 }
9484 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009485 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009486 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009487 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009488 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009489 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009490 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009491 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009492 if($Base{"Type"}=~/Struct|Class/)
9493 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009494 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009495 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9496 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009497 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009499 }
9500 }
9501 }
9502 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009503
9504 # mapping {short name => symbols}
9505 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009506 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009507 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009508 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009509 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009510 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009511 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009512 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009513 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9514 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009515 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009516 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009517 }
9518 }
9519 }
9520 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009521
9522 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009523 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009524 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009525 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009526 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009527 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9528 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009529 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009530 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009531 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009532 $ClassNames{$LibVersion}{$TName} = 1;
9533 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009535 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9536 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009537 }
9538 }
9539 }
9540 }
9541 }
9542}
9543
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009544sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009545{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009546 my ($Tid, $LibVersion) = @_;
9547 if(not $Tid) {
9548 return $Tid;
9549 }
9550
9551 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9552 {
9553 if($TName_Tid{$LibVersion}{$Name}) {
9554 return $TName_Tid{$LibVersion}{$Name};
9555 }
9556 }
9557
9558 return $Tid;
9559}
9560
9561sub register_SymbolUsage($$$)
9562{
9563 my ($InfoId, $UsedType, $LibVersion) = @_;
9564
9565 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9566 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9567 {
9568 register_TypeUsage($RTid, $UsedType, $LibVersion);
9569 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9570 }
9571 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9572 {
9573 register_TypeUsage($FCid, $UsedType, $LibVersion);
9574 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9575
9576 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9577 { # register "this" pointer
9578 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9579 }
9580 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9581 { # register "this" pointer (const method)
9582 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9583 }
9584 }
9585 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9586 {
9587 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9588 {
9589 register_TypeUsage($PTid, $UsedType, $LibVersion);
9590 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9591 }
9592 }
9593 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9594 {
9595 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9596 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9597 register_TypeUsage($TTid, $UsedType, $LibVersion);
9598 }
9599 }
9600}
9601
9602sub register_TypeUsage($$$)
9603{
9604 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009605 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009606 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009607 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009608 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009609 { # already registered
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
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009613 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009614 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009615 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009616 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009617 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009618 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9619 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9620 }
9621 }
9622
9623 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9624 {
9625 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009626 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009627 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009628 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9629 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009630 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009631 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9632 {
9633 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9634 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009635 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009636 }
9637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009638 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009640 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009641 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9642 {
9643 register_TypeUsage($MTid, $UsedType, $LibVersion);
9644 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009645 }
9646 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009647 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009648 or $TInfo{"Type"} eq "MethodPtr"
9649 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009650 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009651 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009652 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009653 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009654 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009655 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009656 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9657 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009658 }
9659 }
9660 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009661 if($TInfo{"Type"} eq "FieldPtr")
9662 {
9663 if(my $RTid = $TInfo{"Return"}) {
9664 register_TypeUsage($RTid, $UsedType, $LibVersion);
9665 }
9666 if(my $CTid = $TInfo{"Class"}) {
9667 register_TypeUsage($CTid, $UsedType, $LibVersion);
9668 }
9669 }
9670 if($TInfo{"Type"} eq "MethodPtr")
9671 {
9672 if(my $CTid = $TInfo{"Class"}) {
9673 register_TypeUsage($CTid, $UsedType, $LibVersion);
9674 }
9675 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009676 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009677 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009678 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009679 $UsedType->{$TypeId} = 1;
9680 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9681 {
9682 register_TypeUsage($BTid, $UsedType, $LibVersion);
9683 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9684 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009685 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009686 else
9687 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9688 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009689 }
9690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009691}
9692
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009693sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009694{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009695 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9696
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009697 if($Level eq "Dump")
9698 {
9699 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9700 { # TODO: check if this symbol is from
9701 # base classes of other target symbols
9702 return 1;
9703 }
9704 }
9705
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009706 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9707 { # stdc++ interfaces
9708 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009709 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009710
9711 my $Target = 0;
9712 if(my $Header = $SInfo->{"Header"}) {
9713 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9714 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009715 if($ExtendedCheck)
9716 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009717 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009718 $Target = 1;
9719 }
9720 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009721 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009722 {
9723 if($Target)
9724 {
9725 if($Level eq "Dump")
9726 { # dumped
9727 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009728 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009729 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009730 return 1;
9731 }
9732 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009733 else {
9734 return 1;
9735 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009737 elsif($Level eq "Source")
9738 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009739 return 1;
9740 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009741 elsif($Level eq "Binary")
9742 { # checked
9743 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9744 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9745 return 1;
9746 }
9747 }
9748 }
9749 }
9750 else
9751 { # library is available
9752 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9753 { # exported symbols
9754 return 1;
9755 }
9756 if($Level eq "Dump")
9757 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009758 if($BinaryOnly)
9759 {
9760 if($SInfo->{"Data"})
9761 {
9762 if($Target) {
9763 return 1;
9764 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009765 }
9766 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009767 else
9768 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009769 if($Target) {
9770 return 1;
9771 }
9772 }
9773 }
9774 elsif($Level eq "Source")
9775 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009776 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009777 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009778 { # skip LOCAL symbols
9779 if($Target) {
9780 return 1;
9781 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009782 }
9783 }
9784 elsif($Level eq "Binary")
9785 { # checked
9786 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9787 {
9788 if($Target) {
9789 return 1;
9790 }
9791 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009792 }
9793 }
9794 return 0;
9795}
9796
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009797sub cleanDump($)
9798{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009799 my $LibVersion = $_[0];
9800 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9801 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009802 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9803 {
9804 delete($SymbolInfo{$LibVersion}{$InfoId});
9805 next;
9806 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009807 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009808 if(not $MnglName)
9809 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009810 delete($SymbolInfo{$LibVersion}{$InfoId});
9811 next;
9812 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009813 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009814 if(not $ShortName)
9815 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009816 delete($SymbolInfo{$LibVersion}{$InfoId});
9817 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009818 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009819 if($MnglName eq $ShortName)
9820 { # remove duplicate data
9821 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
9823 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9824 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9825 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009826 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9827 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9828 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009829 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009831 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009832 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009833 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9834 {
9835 delete($TypeInfo{$LibVersion}{$Tid});
9836 next;
9837 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009838 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009839 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009840 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009841 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9842 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9843 }
9844 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009845 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9846 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9847 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009848 }
9849}
9850
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009851sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009852{
9853 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009854
9855 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9856 {
9857 if(defined $TypeInfo{$LibVersion}{$Dupl})
9858 {
9859 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9860 { # duplicate
9861 return 0;
9862 }
9863 }
9864 }
9865
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009866 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9867
9868 if(isBuiltIn($THeader)) {
9869 return 0;
9870 }
9871
9872 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9873 return 0;
9874 }
9875
9876 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9877 return 0;
9878 }
9879
9880 if(selfTypedef($Tid, $LibVersion)) {
9881 return 0;
9882 }
9883
9884 if(not isTargetType($Tid, $LibVersion)) {
9885 return 0;
9886 }
9887
9888 return 0;
9889}
9890
9891sub isTargetType($$)
9892{
9893 my ($Tid, $LibVersion) = @_;
9894
9895 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9896 { # derived
9897 return 1;
9898 }
9899
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009900 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009901 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009902 if(not is_target_header($THeader, $LibVersion))
9903 { # from target headers
9904 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009905 }
9906 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009907 else
9908 { # NOTE: if type is defined in source
9909 if($UsedDump{$LibVersion}{"Public"})
9910 {
9911 if(isPrivateABI($Tid, $LibVersion)) {
9912 return 0;
9913 }
9914 else {
9915 return 1;
9916 }
9917 }
9918 else {
9919 return 0;
9920 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009921 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009922
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009923 if($SkipInternalTypes)
9924 {
9925 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9926 {
9927 return 0;
9928 }
9929 }
9930
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009931 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009932}
9933
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009934sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009935{ # remove unused data types from the ABI dump
9936 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009937
9938 my %UsedType = ();
9939
9940 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009941 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009942 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009943 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009944 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009945 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009946 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009947 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009948 next;
9949 }
9950
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009951 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009952 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009953 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009954 {
9955 my %Tree = ();
9956 register_TypeUsage($Tid, \%Tree, $LibVersion);
9957
9958 my $Tmpl = 0;
9959 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9960 {
9961 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9962 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9963 {
9964 $Tmpl = 1;
9965 last;
9966 }
9967 }
9968 if(not $Tmpl)
9969 {
9970 foreach (keys(%Tree)) {
9971 $UsedType{$_} = 1;
9972 }
9973 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009974 }
9975 }
9976 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009977
9978 my %Delete = ();
9979
9980 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009981 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009982 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009983 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009984 next;
9985 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009986
9987 if($Kind eq "Extra")
9988 {
9989 my %Tree = ();
9990 register_TypeUsage($Tid, \%Tree, $LibVersion);
9991
9992 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9993 {
9994 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9995 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9996 {
9997 $Delete{$Tid} = 1;
9998 last;
9999 }
10000 }
10001 }
10002 else
10003 {
10004 # remove type
10005 delete($TypeInfo{$LibVersion}{$Tid});
10006 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010007 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010008
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010009 if($Kind eq "Extra")
10010 { # remove duplicates
10011 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10012 {
10013 if($UsedType{$Tid})
10014 { # All & Extended
10015 next;
10016 }
10017
10018 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10019
10020 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10021 delete($TypeInfo{$LibVersion}{$Tid});
10022 }
10023 }
10024 }
10025
10026 foreach my $Tid (keys(%Delete))
10027 {
10028 delete($TypeInfo{$LibVersion}{$Tid});
10029 }
10030}
10031
10032sub check_Completeness($$)
10033{
10034 my ($Info, $LibVersion) = @_;
10035
10036 # data types
10037 if(defined $Info->{"Memb"})
10038 {
10039 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10040 {
10041 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10042 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10043 }
10044 }
10045 }
10046 if(defined $Info->{"Base"})
10047 {
10048 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10049 check_TypeInfo($Bid, $LibVersion);
10050 }
10051 }
10052 if(defined $Info->{"BaseType"}) {
10053 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10054 }
10055 if(defined $Info->{"TParam"})
10056 {
10057 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10058 {
10059 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10060 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10061 next;
10062 }
10063 if($TName eq "_BoolType") {
10064 next;
10065 }
10066 if($TName=~/\Asizeof\(/) {
10067 next;
10068 }
10069 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10070 check_TypeInfo($Tid, $LibVersion);
10071 }
10072 else
10073 {
10074 if(defined $Debug) {
10075 printMsg("WARNING", "missed type $TName");
10076 }
10077 }
10078 }
10079 }
10080
10081 # symbols
10082 if(defined $Info->{"Param"})
10083 {
10084 foreach my $Pos (keys(%{$Info->{"Param"}}))
10085 {
10086 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10087 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10088 }
10089 }
10090 }
10091 if(defined $Info->{"Return"}) {
10092 check_TypeInfo($Info->{"Return"}, $LibVersion);
10093 }
10094 if(defined $Info->{"Class"}) {
10095 check_TypeInfo($Info->{"Class"}, $LibVersion);
10096 }
10097}
10098
10099sub check_TypeInfo($$)
10100{
10101 my ($Tid, $LibVersion) = @_;
10102
10103 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10104 return;
10105 }
10106 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10107
10108 if(defined $TypeInfo{$LibVersion}{$Tid})
10109 {
10110 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10111 printMsg("ERROR", "missed type name ($Tid)");
10112 }
10113 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10114 }
10115 else {
10116 printMsg("ERROR", "missed type id $Tid");
10117 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010118}
10119
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010120sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010121{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010122 my ($TypeId, $LibVersion) = @_;
10123 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010124 if($Type{"Type"} eq "Typedef")
10125 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010126 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010127 if($Base{"Type"}=~/Class|Struct/)
10128 {
10129 if($Type{"Name"} eq $Base{"Name"}) {
10130 return 1;
10131 }
10132 elsif($Type{"Name"}=~/::(\w+)\Z/)
10133 {
10134 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10135 { # QPointer<QWidget>::QPointer
10136 return 1;
10137 }
10138 }
10139 }
10140 }
10141 return 0;
10142}
10143
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010144sub addExtension($)
10145{
10146 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010147 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010149 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010150 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010151 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10152 $TName=~s/\A(struct|union|class|enum) //;
10153 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010154
10155 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10156 "Header" => "extended.h",
10157 "ShortName" => $Symbol,
10158 "MnglName" => $Symbol,
10159 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10160 );
10161
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010162 $ExtendedSymbols{$Symbol} = 1;
10163 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10164 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010165 }
10166 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010167 $ExtendedSymbols{"external_func_0"} = 1;
10168 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10169 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010170}
10171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172sub findMethod($$$)
10173{
10174 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010175 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176 {
10177 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10178 return $VirtMethodInClass;
10179 }
10180 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10181 return $VirtMethodInBaseClasses;
10182 }
10183 }
10184 return "";
10185}
10186
10187sub findMethod_Class($$$)
10188{
10189 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010190 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010191 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10192 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10193 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10194 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10195 { # search for interface with the same parameters suffix (overridden)
10196 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10197 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010198 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10199 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010200 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10201 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010202 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10203 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10204 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10205 return $Candidate;
10206 }
10207 }
10208 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010209 else
10210 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010211 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10212 return $Candidate;
10213 }
10214 }
10215 }
10216 }
10217 return "";
10218}
10219
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010220sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010221{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010222 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010223 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010224 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010225 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10226 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010227 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010228 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010229 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010230 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10231 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010232 { # pure virtual D2-destructors are marked as "virt" in the dump
10233 # virtual D2-destructors are NOT marked as "virt" in the dump
10234 # both destructors are not presented in the v-table
10235 next;
10236 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010237 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010238 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010240 }
10241}
10242
10243sub registerOverriding($)
10244{
10245 my $LibVersion = $_[0];
10246 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010247 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010248 foreach my $ClassName (@Classes)
10249 {
10250 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10251 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010252 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10253 { # pure virtuals
10254 next;
10255 }
10256 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10257 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010258 {
10259 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10260 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10261 { # both overridden virtual methods
10262 # and implemented pure virtual methods
10263 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10264 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10265 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010267 }
10268 }
10269 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10270 delete($VirtualTable{$LibVersion}{$ClassName});
10271 }
10272 }
10273}
10274
10275sub setVirtFuncPositions($)
10276{
10277 my $LibVersion = $_[0];
10278 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10279 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010280 my ($Num, $Rel) = (1, 0);
10281
10282 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010283 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010284 if($UsedDump{$LibVersion}{"DWARF"}) {
10285 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10286 }
10287 else {
10288 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10289 }
10290 foreach my $VirtFunc (@Funcs)
10291 {
10292 if($UsedDump{$LibVersion}{"DWARF"}) {
10293 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10294 }
10295 else {
10296 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10297 }
10298
10299 # set relative positions
10300 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10301 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10302 { # relative position excluding added and removed virtual functions
10303 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10304 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10305 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010309 }
10310 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010311 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 {
10313 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010314 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010315 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010316 }
10317 }
10318}
10319
10320sub get_sub_classes($$$)
10321{
10322 my ($ClassId, $LibVersion, $Recursive) = @_;
10323 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10324 my @Subs = ();
10325 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10326 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010327 if($Recursive)
10328 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010329 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10330 push(@Subs, $SubSubId);
10331 }
10332 }
10333 push(@Subs, $SubId);
10334 }
10335 return @Subs;
10336}
10337
10338sub get_base_classes($$$)
10339{
10340 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010341 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 return () if(not defined $ClassType{"Base"});
10343 my @Bases = ();
10344 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10345 keys(%{$ClassType{"Base"}}))
10346 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010347 if($Recursive)
10348 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010349 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10350 push(@Bases, $SubBaseId);
10351 }
10352 }
10353 push(@Bases, $BaseId);
10354 }
10355 return @Bases;
10356}
10357
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010358sub getVTable_Model($$)
10359{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010360 my ($ClassId, $LibVersion) = @_;
10361 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10362 my @Elements = ();
10363 foreach my $BaseId (@Bases, $ClassId)
10364 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010365 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010366 {
10367 if(defined $VirtualTable{$LibVersion}{$BName})
10368 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010369 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10370 if($UsedDump{$LibVersion}{"DWARF"}) {
10371 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10372 }
10373 else {
10374 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10375 }
10376 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010377 push(@Elements, $VFunc);
10378 }
10379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010380 }
10381 }
10382 return @Elements;
10383}
10384
10385sub getVShift($$)
10386{
10387 my ($ClassId, $LibVersion) = @_;
10388 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10389 my $VShift = 0;
10390 foreach my $BaseId (@Bases)
10391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010392 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010393 {
10394 if(defined $VirtualTable{$LibVersion}{$BName}) {
10395 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010397 }
10398 }
10399 return $VShift;
10400}
10401
10402sub getShift($$)
10403{
10404 my ($ClassId, $LibVersion) = @_;
10405 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10406 my $Shift = 0;
10407 foreach my $BaseId (@Bases)
10408 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010409 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010410 {
10411 if($Size!=1)
10412 { # not empty base class
10413 $Shift+=$Size;
10414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010415 }
10416 }
10417 return $Shift;
10418}
10419
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420sub getVTable_Size($$)
10421{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010422 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010423 my $Size = 0;
10424 # three approaches
10425 if(not $Size)
10426 { # real size
10427 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10428 $Size = keys(%VTable);
10429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010431 if(not $Size)
10432 { # shared library symbol size
10433 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10434 $Size /= $WORD_SIZE{$LibVersion};
10435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010436 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010437 if(not $Size)
10438 { # model size
10439 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10440 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10441 }
10442 }
10443 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010444}
10445
10446sub isCopyingClass($$)
10447{
10448 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010449 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450}
10451
10452sub isLeafClass($$)
10453{
10454 my ($ClassId, $LibVersion) = @_;
10455 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10456}
10457
10458sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010459{ # check structured type for public fields
10460 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010461}
10462
10463sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010464{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465 my ($TypePtr, $Skip, $Start, $End) = @_;
10466 return 0 if(not $TypePtr);
10467 if($End==-1) {
10468 $End = keys(%{$TypePtr->{"Memb"}})-1;
10469 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010470 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010471 {
10472 if($Skip and $Skip->{$MemPos})
10473 { # skip removed/added fields
10474 next;
10475 }
10476 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10477 {
10478 if(isPublic($TypePtr, $MemPos)) {
10479 return ($MemPos+1);
10480 }
10481 }
10482 }
10483 return 0;
10484}
10485
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486sub isReserved($)
10487{ # reserved fields == private
10488 my $MName = $_[0];
10489 if($MName=~/reserved|padding|f_spare/i) {
10490 return 1;
10491 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010492 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493 return 1;
10494 }
10495 if($MName=~/(pad\d+)/i) {
10496 return 1;
10497 }
10498 return 0;
10499}
10500
10501sub isPublic($$)
10502{
10503 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 return 0 if(not $TypePtr);
10506 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10507 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010508
10509 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10510 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010511 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010512 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010514
10515 # by name in C language
10516 # TODO: add other methods to detect private members
10517 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010518 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010519 { # C-styled private data
10520 return 0;
10521 }
10522 if(lc($MName) eq "abi")
10523 { # ABI information/reserved field
10524 return 0;
10525 }
10526 if(isReserved($MName))
10527 { # reserved fields
10528 return 0;
10529 }
10530
10531 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010532}
10533
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010534sub getVTable_Real($$)
10535{
10536 my ($ClassName, $LibVersion) = @_;
10537 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10538 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010539 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010540 if(defined $Type{"VTable"}) {
10541 return %{$Type{"VTable"}};
10542 }
10543 }
10544 return ();
10545}
10546
10547sub cmpVTables($)
10548{
10549 my $ClassName = $_[0];
10550 my $Res = cmpVTables_Real($ClassName, 1);
10551 if($Res==-1) {
10552 $Res = cmpVTables_Model($ClassName);
10553 }
10554 return $Res;
10555}
10556
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557sub cmpVTables_Model($)
10558{
10559 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010560 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010562 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010563 return 1;
10564 }
10565 }
10566 return 0;
10567}
10568
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570{
10571 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010572 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10573 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010574 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010575 my %VTable_Old = getVTable_Real($ClassName, 1);
10576 my %VTable_New = getVTable_Real($ClassName, 2);
10577 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010580 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010581 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10583 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010584 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010585 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010586 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 my $Entry1 = $VTable_Old{$Offset};
10589 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010591 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010592 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010595 $Entry1 = simpleVEntry($Entry1);
10596 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010597
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010598 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010599 { # NOTE: problem with vtable-dumper
10600 next;
10601 }
10602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603 if($Entry1 ne $Entry2)
10604 { # register as changed
10605 if($Entry1=~/::([^:]+)\Z/)
10606 {
10607 my $M1 = $1;
10608 if($Entry2=~/::([^:]+)\Z/)
10609 {
10610 my $M2 = $1;
10611 if($M1 eq $M2)
10612 { # overridden
10613 next;
10614 }
10615 }
10616 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010617 if(differentDumps("G"))
10618 {
10619 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10620 {
10621 # GCC 4.6.1: -0x00000000000000010
10622 # GCC 4.7.0: -16
10623 next;
10624 }
10625 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010626 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010627 }
10628 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010630}
10631
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010632sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010634 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10636 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010637 my $ClassId = $TName_Tid{1}{$ClassName};
10638 if(isPrivateABI($ClassId, 1)) {
10639 next;
10640 }
10641
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010642 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010643 { # already registered
10644 next;
10645 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010646 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010648 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010649 foreach my $Symbol (@Affected)
10650 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010651 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010652 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 "Target"=>$ClassName);
10654 }
10655 }
10656 }
10657}
10658
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010659sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010660{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010661 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010662 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010664 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010666
10667 if(isPrivateABI($ClassId, 1)) {
10668 next;
10669 }
10670
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010671 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010672 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010673 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010674 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010675 if($TName_Tid{1}{$ClassName}
10676 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010677 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010678 if(defined $CompleteSignature{1}{$Symbol}
10679 and $CompleteSignature{1}{$Symbol}{"Virt"})
10680 { # override some method in v.1
10681 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010682 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010683 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010684 }
10685 }
10686 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010687 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010689 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010690 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010691 if($TName_Tid{2}{$ClassName}
10692 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010693 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010694 if(defined $CompleteSignature{2}{$Symbol}
10695 and $CompleteSignature{2}{$Symbol}{"Virt"})
10696 { # override some method in v.2
10697 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010698 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010699 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010700 }
10701 }
10702 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010703 if($Level eq "Binary")
10704 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010705 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010706 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10707 { # check replacements, including pure virtual methods
10708 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10709 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010710 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010711 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10712 if($AddedPos==$RemovedPos)
10713 {
10714 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10715 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10716 last; # other methods will be reported as "added" or "removed"
10717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010719 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10720 {
10721 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10722 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010723 next;
10724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010725 my $ProblemType = "Virtual_Replacement";
10726 my @Affected = ($RemovedVFunc);
10727 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10728 { # pure methods
10729 if(not isUsedClass($ClassId, 1, $Level))
10730 { # not a parameter of some exported method
10731 next;
10732 }
10733 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010734
10735 # affected all methods (both virtual and non-virtual ones)
10736 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10737 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010739 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010740 foreach my $AffectedInt (@Affected)
10741 {
10742 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10743 { # affected exported methods only
10744 next;
10745 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010746 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10747 next;
10748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010749 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10750 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010751 "Target"=>get_Signature($AddedVFunc, 2),
10752 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 }
10755 }
10756 }
10757 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010758 if(not checkDump(1, "2.0")
10759 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010760 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010761 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010762 return;
10763 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010764 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010765 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010766 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010768
10769 if(isPrivateABI($ClassId_Old, 1)) {
10770 next;
10771 }
10772
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 if(not isCreatable($ClassId_Old, 1))
10774 { # skip classes without public constructors (including auto-generated)
10775 # example: class has only a private exported or private inline constructor
10776 next;
10777 }
10778 if($ClassName=~/>/)
10779 { # skip affected template instances
10780 next;
10781 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010782 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010783 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010784 if(not $ClassId_New) {
10785 next;
10786 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010787 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010788 if($Class_New{"Type"}!~/Class|Struct/)
10789 { # became typedef
10790 if($Level eq "Binary") {
10791 next;
10792 }
10793 if($Level eq "Source")
10794 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010795 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010796 if($Class_New{"Type"}!~/Class|Struct/) {
10797 next;
10798 }
10799 $ClassId_New = $Class_New{"Tid"};
10800 }
10801 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010802
10803 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10804 { # incomplete info in the ABI dump
10805 next;
10806 }
10807
10808
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010809 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10810 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 +040010811
10812 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10813 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010815 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010816 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10817 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010818 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10819 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010820 my $Shift_Old = getShift($ClassId_Old, 1);
10821 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010822 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 my ($Added, $Removed) = (0, 0);
10824 my @StableBases_Old = ();
10825 foreach my $BaseId (@Bases_Old)
10826 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010827 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010828 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 push(@StableBases_Old, $BaseId);
10830 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010831 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010832 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010833 { # removed base
10834 # excluding namespace::SomeClass to SomeClass renaming
10835 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010836 if($Level eq "Binary")
10837 { # Binary-level
10838 if($Shift_Old ne $Shift_New)
10839 { # affected fields
10840 if(havePubFields(\%Class_Old)) {
10841 $ProblemKind .= "_And_Shift";
10842 }
10843 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10844 $ProblemKind .= "_And_Size";
10845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010846 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010847 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10848 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010849 { # affected v-table
10850 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010851 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010852 }
10853 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010854 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010855 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10856 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010857 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10858 {
10859 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10860 if($ProblemKind=~/VTable/) {
10861 $VTableChanged_M{$SubName}=1;
10862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010863 }
10864 }
10865 foreach my $Interface (@Affected)
10866 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010867 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10868 next;
10869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010871 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010872 "Target"=>$BaseName,
10873 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10874 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10875 "Shift"=>abs($Shift_New-$Shift_Old) );
10876 }
10877 $Removed+=1;
10878 }
10879 }
10880 my @StableBases_New = ();
10881 foreach my $BaseId (@Bases_New)
10882 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010883 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010884 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010885 push(@StableBases_New, $BaseId);
10886 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010887 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010888 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010889 { # added base
10890 # excluding namespace::SomeClass to SomeClass renaming
10891 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010892 if($Level eq "Binary")
10893 { # Binary-level
10894 if($Shift_Old ne $Shift_New)
10895 { # affected fields
10896 if(havePubFields(\%Class_Old)) {
10897 $ProblemKind .= "_And_Shift";
10898 }
10899 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10900 $ProblemKind .= "_And_Size";
10901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010902 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010903 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10904 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010905 { # affected v-table
10906 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010907 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010908 }
10909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010910 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010911 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10912 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010913 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10914 {
10915 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10916 if($ProblemKind=~/VTable/) {
10917 $VTableChanged_M{$SubName}=1;
10918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010919 }
10920 }
10921 foreach my $Interface (@Affected)
10922 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010923 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10924 next;
10925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010926 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010927 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010928 "Target"=>$BaseName,
10929 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10930 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10931 "Shift"=>abs($Shift_New-$Shift_Old) );
10932 }
10933 $Added+=1;
10934 }
10935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010936 if($Level eq "Binary")
10937 { # Binary-level
10938 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010939 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10940 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010942 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010943 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010944 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010945 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010946 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10947 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010948 if($NewPos!=$OldPos)
10949 { # changed position of the base class
10950 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010951 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010952 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10953 next;
10954 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010955 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10956 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010957 "Target"=>$BaseName,
10958 "Old_Value"=>$OldPos-1,
10959 "New_Value"=>$NewPos-1 );
10960 }
10961 }
10962 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10963 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10964 { # became non-virtual base
10965 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10966 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010967 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10968 next;
10969 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010970 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10971 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010972 "Target"=>$BaseName );
10973 }
10974 }
10975 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10976 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10977 { # became virtual base
10978 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10979 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010980 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10981 next;
10982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10984 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010985 "Target"=>$BaseName );
10986 }
10987 }
10988 }
10989 }
10990 # detect size changes in base classes
10991 if($Shift_Old!=$Shift_New)
10992 { # size of allocable class
10993 foreach my $BaseId (@StableBases_Old)
10994 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010995 my %BaseType = get_Type($BaseId, 1);
10996 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010997 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010998 if($Size_Old ne $Size_New
10999 and $Size_Old and $Size_New)
11000 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011001 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 if(isCopyingClass($BaseId, 1)) {
11003 $ProblemType = "Size_Of_Copying_Class";
11004 }
11005 elsif($AllocableClass{1}{$BaseType{"Name"}})
11006 {
11007 if($Size_New>$Size_Old)
11008 { # increased size
11009 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011010 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011011 else
11012 { # decreased size
11013 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11014 if(not havePubFields(\%Class_Old))
11015 { # affected class has no public members
11016 next;
11017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011018 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011019 }
11020 next if(not $ProblemType);
11021 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11022 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011023 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11024 next;
11025 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011026 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11027 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011028 "Target"=>$BaseType{"Name"},
11029 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11030 "New_Size"=>$Size_New*$BYTE_SIZE );
11031 }
11032 }
11033 }
11034 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011035 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011036 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011037 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011038 { # compare virtual tables size in base classes
11039 my $VShift_Old = getVShift($ClassId_Old, 1);
11040 my $VShift_New = getVShift($ClassId_New, 2);
11041 if($VShift_Old ne $VShift_New)
11042 { # changes in the base class or changes in the list of base classes
11043 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11044 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11045 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011046 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011047 foreach my $BaseId (@AllBases_Old)
11048 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011049 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011050 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011051 { # lost base
11052 next;
11053 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011054 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11055 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 if($VSize_Old!=$VSize_New)
11057 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011058 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011059 { # TODO: affected non-virtual methods?
11060 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011061 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11062 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011063 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011064 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # skip interfaces that have not changed the absolute virtual position
11066 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011068 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11069 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011071 $VTableChanged_M{$BaseType{"Name"}} = 1;
11072 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011073 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11074 { # the reason of the layout change: added virtual functions
11075 next if($VirtualReplacement{$VirtFunc});
11076 my $ProblemType = "Added_Virtual_Method";
11077 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11078 $ProblemType = "Added_Pure_Virtual_Method";
11079 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011080 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011081 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011082 "Target"=>get_Signature($VirtFunc, 2) );
11083 }
11084 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11085 { # the reason of the layout change: removed virtual functions
11086 next if($VirtualReplacement{$VirtFunc});
11087 my $ProblemType = "Removed_Virtual_Method";
11088 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11089 $ProblemType = "Removed_Pure_Virtual_Method";
11090 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011091 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011092 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011093 "Target"=>get_Signature($VirtFunc, 1) );
11094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011095 }
11096 }
11097 }
11098 }
11099 }
11100 }
11101 }
11102}
11103
11104sub isCreatable($$)
11105{
11106 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011107 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011108 or isCopyingClass($ClassId, $LibVersion)) {
11109 return 1;
11110 }
11111 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11112 { # Fix for incomplete data: if this class has
11113 # a base class then it should also has a constructor
11114 return 1;
11115 }
11116 if($ReturnedClass{$LibVersion}{$ClassId})
11117 { # returned by some method of this class
11118 # or any other class
11119 return 1;
11120 }
11121 return 0;
11122}
11123
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011125{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011126 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011127 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11128 { # parameter of some exported method
11129 return 1;
11130 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011131 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11132 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011133 { # method from target class
11134 return 1;
11135 }
11136 return 0;
11137}
11138
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011139sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011140{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011141 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011142 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 # - virtual
11144 # - pure-virtual
11145 # - non-virtual
11146 if($CompleteSignature{1}{$Interface}{"Data"})
11147 { # global data is not affected
11148 return;
11149 }
11150 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011151 if(not $Class_Id) {
11152 return;
11153 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011154 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 if(cmpVTables_Real($CName, 1)==0)
11156 { # no changes
11157 return;
11158 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011159 $CheckedTypes{$Level}{$CName} = 1;
11160 if($Level eq "Binary")
11161 { # Binary-level
11162 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11163 and not isUsedClass($Class_Id, 1, $Level))
11164 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011165 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011166 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011167 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011168 }
11169 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11170 {
11171 if(defined $VirtualTable{2}{$CName}{$Func}
11172 and defined $CompleteSignature{2}{$Func})
11173 {
11174 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11175 and $CompleteSignature{2}{$Func}{"PureVirt"})
11176 { # became pure virtual
11177 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11178 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011179 "Target"=>get_Signature_M($Func, 1) );
11180 $VTableChanged_M{$CName} = 1;
11181 }
11182 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11183 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11184 { # became non-pure virtual
11185 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11186 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011187 "Target"=>get_Signature_M($Func, 1) );
11188 $VTableChanged_M{$CName} = 1;
11189 }
11190 }
11191 }
11192 if($Level eq "Binary")
11193 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 # check virtual table structure
11195 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11196 {
11197 next if($Interface eq $AddedVFunc);
11198 next if($VirtualReplacement{$AddedVFunc});
11199 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11200 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11201 { # pure virtual methods affect all others (virtual and non-virtual)
11202 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011203 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011204 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011205 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011207 elsif(not defined $VirtualTable{1}{$CName}
11208 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011209 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011210 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011211 { # became polymorphous class, added v-table pointer
11212 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011213 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011214 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011215 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011216 }
11217 else
11218 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 my $VSize_Old = getVTable_Size($CName, 1);
11220 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011221 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011222 if(isCopyingClass($Class_Id, 1))
11223 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11224 my $ProblemType = "Added_Virtual_Method";
11225 if(isLeafClass($Class_Id, 1)) {
11226 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11227 }
11228 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11229 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011230 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011231 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011233 else
11234 {
11235 my $ProblemType = "Added_Virtual_Method";
11236 if(isLeafClass($Class_Id, 1)) {
11237 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11238 }
11239 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11240 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011241 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011242 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244 }
11245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011246 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11247 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011248 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011249 if(defined $VirtualTable{1}{$CName}
11250 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011251 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011252 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11253 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011254
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011255 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011256 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011257 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11258 foreach my $ASymbol (@Affected)
11259 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011260 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11261 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011262 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011263 next;
11264 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011265 }
11266 $CheckedSymbols{$Level}{$ASymbol} = 1;
11267 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11268 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011269 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011270 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011273 }
11274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 else {
11276 # safe
11277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011279 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11280 {
11281 next if($VirtualReplacement{$RemovedVFunc});
11282 if($RemovedVFunc eq $Interface
11283 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11284 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011285 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011286 next;
11287 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011288 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011289 { # became non-polymorphous class, removed v-table pointer
11290 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11291 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011292 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011293 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011294 }
11295 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11296 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11297 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011298 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011299 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011300 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11301 next;
11302 }
11303 my $VPos_New = -1;
11304 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011305 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011306 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11307 }
11308 else
11309 {
11310 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011311 next;
11312 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011313 }
11314 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11315 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11316 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11317 {
11318 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11319 foreach my $ASymbol (@Affected)
11320 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011321 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11322 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011323 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011324 next;
11325 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011326 }
11327 my $ProblemType = "Removed_Virtual_Method";
11328 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11329 $ProblemType = "Removed_Pure_Virtual_Method";
11330 }
11331 $CheckedSymbols{$Level}{$ASymbol} = 1;
11332 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11333 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011334 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011335 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011336 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011337 }
11338 }
11339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011340 }
11341 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011342 else
11343 { # Source-level
11344 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011346 next if($Interface eq $AddedVFunc);
11347 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011348 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011349 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11350 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011351 "Target"=>get_Signature($AddedVFunc, 2) );
11352 }
11353 }
11354 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11355 {
11356 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11357 {
11358 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11359 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011360 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011361 }
11362 }
11363 }
11364}
11365
11366sub find_MemberPair_Pos_byName($$)
11367{
11368 my ($Member_Name, $Pair_Type) = @_;
11369 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11370 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11371 {
11372 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11373 {
11374 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11375 $Name=~s/\A[_]+|[_]+\Z//g;
11376 if($Name eq $Member_Name) {
11377 return $MemberPair_Pos;
11378 }
11379 }
11380 }
11381 return "lost";
11382}
11383
11384sub find_MemberPair_Pos_byVal($$)
11385{
11386 my ($Member_Value, $Pair_Type) = @_;
11387 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11388 {
11389 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11390 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11391 return $MemberPair_Pos;
11392 }
11393 }
11394 return "lost";
11395}
11396
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011397sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011398{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011399 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011400 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011401 if( $_->{"T1"} eq $_[0]
11402 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011403 {
11404 return 1;
11405 }
11406 }
11407 return 0;
11408}
11409
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011410sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011411{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011412 my %IDs = (
11413 "T1" => $_[0],
11414 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011415 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011416 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011417}
11418
11419sub isRenamed($$$$$)
11420{
11421 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11422 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11423 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011424 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011425 if(not defined $Type2->{"Memb"}{$MemPos}) {
11426 return "";
11427 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011428 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011429 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011430
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011431 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11432 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011433 if($MemberPair_Pos_Rev eq "lost")
11434 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011435 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11436 { # base type match
11437 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011438 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11440 { # exact type match
11441 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011443 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11444 { # size match
11445 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011447 if(isReserved($Pair_Name))
11448 { # reserved fields
11449 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011450 }
11451 }
11452 return "";
11453}
11454
11455sub isLastElem($$)
11456{
11457 my ($Pos, $TypeRef) = @_;
11458 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011459 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011460 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11461 return 1;
11462 }
11463 elsif($Name=~/END|NLIMITS\Z/)
11464 { # __RLIMIT_NLIMITS
11465 return 1;
11466 }
11467 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11468 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11469 { # NImageFormats, NColorRoles
11470 return 1;
11471 }
11472 return 0;
11473}
11474
11475sub nonComparable($$)
11476{
11477 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011478
11479 my $N1 = $T1->{"Name"};
11480 my $N2 = $T2->{"Name"};
11481
11482 $N1=~s/\A(struct|union|enum) //;
11483 $N2=~s/\A(struct|union|enum) //;
11484
11485 if($N1 ne $N2
11486 and not isAnon($N1)
11487 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011488 { # different names
11489 if($T1->{"Type"} ne "Pointer"
11490 or $T2->{"Type"} ne "Pointer")
11491 { # compare base types
11492 return 1;
11493 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011494 if($N1!~/\Avoid\s*\*/
11495 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011496 {
11497 return 1;
11498 }
11499 }
11500 elsif($T1->{"Type"} ne $T2->{"Type"})
11501 { # different types
11502 if($T1->{"Type"} eq "Class"
11503 and $T2->{"Type"} eq "Struct")
11504 { # "class" to "struct"
11505 return 0;
11506 }
11507 elsif($T2->{"Type"} eq "Class"
11508 and $T1->{"Type"} eq "Struct")
11509 { # "struct" to "class"
11510 return 0;
11511 }
11512 else
11513 { # "class" to "enum"
11514 # "union" to "class"
11515 # ...
11516 return 1;
11517 }
11518 }
11519 return 0;
11520}
11521
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011522sub isOpaque($)
11523{
11524 my $T = $_[0];
11525 if(not defined $T->{"Memb"})
11526 {
11527 return 1;
11528 }
11529 return 0;
11530}
11531
11532sub removeVPtr($)
11533{ # support for old ABI dumps
11534 my $TPtr = $_[0];
11535 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11536 if($#Pos>=1)
11537 {
11538 foreach my $Pos (0 .. $#Pos-1)
11539 {
11540 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11541 }
11542 delete($TPtr->{"Memb"}{$#Pos});
11543 }
11544}
11545
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011546sub isPrivateABI($$)
11547{
11548 my ($TypeId, $LibVersion) = @_;
11549
11550 if($CheckPrivateABI) {
11551 return 0;
11552 }
11553
11554 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11555 return 1;
11556 }
11557
11558 return 0;
11559}
11560
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011561sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011562{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011563 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011564 return {} if(not $Type1_Id or not $Type2_Id);
11565
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011566 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011567 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011568 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011569 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011570
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011571 my %Type1 = get_Type($Type1_Id, 1);
11572 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011573 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011574 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011575 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011576
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011577 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11578 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011579
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011580 if(defined $UsedDump{1}{"DWARF"})
11581 {
11582 if($Type1_Pure{"Name"} eq "__unknown__"
11583 or $Type2_Pure{"Name"} eq "__unknown__")
11584 { # Error ABI dump
11585 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11586 }
11587 }
11588
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011589 if(isPrivateABI($Type1_Id, 1)) {
11590 return {};
11591 }
11592
11593 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11594 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11595
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011596 my %SubProblems = ();
11597
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011598 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11599 {
11600 if($Type1_Pure{"Type"}=~/Struct|Union/
11601 and $Type2_Pure{"Type"}=~/Struct|Union/)
11602 {
11603 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11604 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011605 if(not defined $UsedDump{1}{"DWARF"}
11606 and not defined $UsedDump{2}{"DWARF"})
11607 {
11608 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11609 "Target"=>$Type1_Pure{"Name"},
11610 "Type_Name"=>$Type1_Pure{"Name"} );
11611 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011612
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011613 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011614 }
11615 }
11616 }
11617
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011618 if(not $Type1_Pure{"Size"}
11619 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011620 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011621 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11622 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11623 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011624 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011626 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011627 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011628 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011629 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011630 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011631 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11632 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11633 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011635 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11636 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011637 }
11638
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011639 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11640 { # support for old ABI dumps
11641 # _vptr field added in 3.0
11642 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11643 {
11644 if(defined $Type2_Pure{"Memb"}
11645 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11646 {
11647 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11648 delete($Type2_Pure{"Memb"}{0});
11649 }
11650 else {
11651 removeVPtr(\%Type2_Pure);
11652 }
11653 }
11654 }
11655 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11656 {
11657 if(defined $Type1_Pure{"Memb"}
11658 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11659 {
11660 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11661 delete($Type1_Pure{"Memb"}{0});
11662 }
11663 else {
11664 removeVPtr(\%Type1_Pure);
11665 }
11666 }
11667 }
11668 }
11669
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011670 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11671 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011672
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011673 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011674 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11675 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011676 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011677 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11678 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011679 if($Base_1{"Name"} ne $Base_2{"Name"})
11680 {
11681 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011682 or differentDumps("V")
11683 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011684 { # different GCC versions or different dumps
11685 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11686 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11687 # std::__va_list and __va_list
11688 $Base_1{"Name"}=~s/\A(\w+::)+//;
11689 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011690 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11691 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011693 }
11694 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11695 and $Base_1{"Name"} ne $Base_2{"Name"})
11696 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011697 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011698 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011699 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 {
11701 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11702 "Target"=>$Typedef_1{"Name"},
11703 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11705 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11706 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011707 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11708 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011709
11710 if(defined $UsedDump{1}{"DWARF"})
11711 {
11712 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11713 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11714 { # Error ABI dump
11715 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11716 }
11717 }
11718
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011719 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011720 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011721 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11722 {
11723 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11724 "Target"=>$Typedef_1{"Name"},
11725 "Type_Name"=>$Typedef_1{"Name"},
11726 "Old_Value"=>$Base_1{"Name"},
11727 "New_Value"=>$Base_2{"Name"} );
11728 }
11729 else
11730 {
11731 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11732 "Target"=>$Typedef_1{"Name"},
11733 "Type_Name"=>$Typedef_1{"Name"},
11734 "Old_Value"=>$Base_1{"Name"},
11735 "New_Value"=>$Base_2{"Name"} );
11736 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011738 }
11739 }
11740 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11741 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011742 my $TT1 = $Type1_Pure{"Type"};
11743 my $TT2 = $Type2_Pure{"Type"};
11744
11745 if($TT1 ne $TT2
11746 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011747 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011748 my $Short1 = $Type1_Pure{"Name"};
11749 my $Short2 = $Type2_Pure{"Name"};
11750
11751 $Short1=~s/\A\Q$TT1\E //ig;
11752 $Short2=~s/\A\Q$TT2\E //ig;
11753
11754 if($Short1 eq $Short2)
11755 {
11756 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11757 "Target"=>$Type1_Pure{"Name"},
11758 "Type_Name"=>$Type1_Pure{"Name"},
11759 "Old_Value"=>lc($Type1_Pure{"Type"}),
11760 "New_Value"=>lc($Type2_Pure{"Type"}) );
11761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011763 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011764 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011765
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011766 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011768 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11769 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11770 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11771 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011772 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011773 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011774 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011775 {
11776 my $ProblemKind = "DataType_Size";
11777 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011778 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 {
11780 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11781 $ProblemKind = "Size_Of_Copying_Class";
11782 }
11783 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11784 {
11785 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11786 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11787 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011788 else
11789 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011790 # descreased size of allocable class
11791 # it has no special effects
11792 }
11793 }
11794 }
11795 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11796 "Target"=>$Type1_Pure{"Name"},
11797 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011798 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011799 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011800 }
11801 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011802 if(defined $Type1_Pure{"BaseType"}
11803 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011804 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011805 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11806 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011807 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011808 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11809 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011810 }
11811 }
11812 }
11813 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11814 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11815 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11816 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11817 { # detect removed and renamed fields
11818 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11819 next if(not $Member_Name);
11820 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);
11821 if($MemberPair_Pos eq "lost")
11822 {
11823 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11824 {
11825 if(isUnnamed($Member_Name))
11826 { # support for old-version dumps
11827 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011828 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011829 next;
11830 }
11831 }
11832 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11833 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011834 $RenamedField{$Member_Pos} = $RenamedTo;
11835 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011836 }
11837 else
11838 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011839 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 }
11841 }
11842 elsif($Type1_Pure{"Type"} eq "Enum")
11843 {
11844 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11845 next if($Member_Value1 eq "");
11846 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11847 if($MemberPair_Pos ne "lost")
11848 { # renamed
11849 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11850 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11851 if($MemberPair_Pos_Rev eq "lost")
11852 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011853 $RenamedField{$Member_Pos} = $RenamedTo;
11854 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011855 }
11856 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011857 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011858 }
11859 }
11860 else
11861 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011862 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011863 }
11864 }
11865 }
11866 else
11867 { # related
11868 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11869 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11870 }
11871 }
11872 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11873 { # detect added fields
11874 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11875 next if(not $Member_Name);
11876 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);
11877 if($MemberPair_Pos eq "lost")
11878 {
11879 if(isUnnamed($Member_Name))
11880 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011881 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011882 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011883 next;
11884 }
11885 }
11886 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11887 {
11888 if(not $RenamedField_Rev{$Member_Pos})
11889 { # added
11890 $AddedField{$Member_Pos}=1;
11891 }
11892 }
11893 }
11894 }
11895 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11896 { # detect moved fields
11897 my (%RelPos, %RelPosName, %AbsPos) = ();
11898 my $Pos = 0;
11899 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11900 { # relative positions in 1st version
11901 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11902 next if(not $Member_Name);
11903 if(not $RemovedField{$Member_Pos})
11904 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011905 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011906 $RelPosName{1}{$Pos} = $Member_Name;
11907 $AbsPos{1}{$Pos++} = $Member_Pos;
11908 }
11909 }
11910 $Pos = 0;
11911 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11912 { # relative positions in 2nd version
11913 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11914 next if(not $Member_Name);
11915 if(not $AddedField{$Member_Pos})
11916 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011917 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011918 $RelPosName{2}{$Pos} = $Member_Name;
11919 $AbsPos{2}{$Pos++} = $Member_Pos;
11920 }
11921 }
11922 foreach my $Member_Name (keys(%{$RelPos{1}}))
11923 {
11924 my $RPos1 = $RelPos{1}{$Member_Name};
11925 my $AbsPos1 = $NameToPosA{$Member_Name};
11926 my $Member_Name2 = $Member_Name;
11927 if(my $RenamedTo = $RenamedField{$AbsPos1})
11928 { # renamed
11929 $Member_Name2 = $RenamedTo;
11930 }
11931 my $RPos2 = $RelPos{2}{$Member_Name2};
11932 if($RPos2 ne "" and $RPos1 ne $RPos2)
11933 { # different relative positions
11934 my $AbsPos2 = $NameToPosB{$Member_Name2};
11935 if($AbsPos1 ne $AbsPos2)
11936 { # different absolute positions
11937 my $ProblemType = "Moved_Field";
11938 if(not isPublic(\%Type1_Pure, $AbsPos1))
11939 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011940 if($Level eq "Source") {
11941 next;
11942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011943 $ProblemType = "Moved_Private_Field";
11944 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011945 if($Level eq "Binary"
11946 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011947 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011948 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011949 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011950 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 if($MemSize1 ne $MemSize2) {
11952 $ProblemType .= "_And_Size";
11953 }
11954 }
11955 if($ProblemType eq "Moved_Private_Field") {
11956 next;
11957 }
11958 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11959 "Target"=>$Member_Name,
11960 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011961 "Old_Value"=>$RPos1,
11962 "New_Value"=>$RPos2 );
11963 }
11964 }
11965 }
11966 }
11967 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011968 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011969 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11970 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011971 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011972 if(my $RenamedTo = $RenamedField{$Member_Pos})
11973 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011974 if(defined $Constants{2}{$Member_Name})
11975 {
11976 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11977 { # define OLD NEW
11978 next; # Safe
11979 }
11980 }
11981
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011982 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11983 {
11984 if(isPublic(\%Type1_Pure, $Member_Pos))
11985 {
11986 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11987 "Target"=>$Member_Name,
11988 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011989 "Old_Value"=>$Member_Name,
11990 "New_Value"=>$RenamedTo );
11991 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011992 elsif(isReserved($Member_Name))
11993 {
11994 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11995 "Target"=>$Member_Name,
11996 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011997 "Old_Value"=>$Member_Name,
11998 "New_Value"=>$RenamedTo );
11999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012000 }
12001 elsif($Type1_Pure{"Type"} eq "Enum")
12002 {
12003 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
12004 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
12005 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012006 "Old_Value"=>$Member_Name,
12007 "New_Value"=>$RenamedTo );
12008 }
12009 }
12010 elsif($RemovedField{$Member_Pos})
12011 { # removed
12012 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12013 {
12014 my $ProblemType = "Removed_Field";
12015 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012016 or isUnnamed($Member_Name))
12017 {
12018 if($Level eq "Source") {
12019 next;
12020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012021 $ProblemType = "Removed_Private_Field";
12022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012023 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012024 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012025 {
12026 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
12027 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028 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 +040012029 { # changed offset
12030 $ProblemType .= "_And_Layout";
12031 }
12032 }
12033 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
12034 { # affected size
12035 $ProblemType .= "_And_Size";
12036 }
12037 }
12038 if($ProblemType eq "Removed_Private_Field") {
12039 next;
12040 }
12041 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12042 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012043 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 }
12045 elsif($Type2_Pure{"Type"} eq "Union")
12046 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012047 if($Level eq "Binary"
12048 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012049 {
12050 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12051 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012052 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053 }
12054 else
12055 {
12056 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12057 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012058 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012059 }
12060 }
12061 elsif($Type1_Pure{"Type"} eq "Enum")
12062 {
12063 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12064 "Target"=>$Member_Name,
12065 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012066 "Old_Value"=>$Member_Name );
12067 }
12068 }
12069 else
12070 { # changed
12071 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12072 if($Type1_Pure{"Type"} eq "Enum")
12073 {
12074 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12075 next if($Member_Value1 eq "");
12076 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12077 next if($Member_Value2 eq "");
12078 if($Member_Value1 ne $Member_Value2)
12079 {
12080 my $ProblemType = "Enum_Member_Value";
12081 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12082 $ProblemType = "Enum_Last_Member_Value";
12083 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012084 if($SkipConstants{1}{$Member_Name}) {
12085 $ProblemType = "Enum_Private_Member_Value";
12086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12088 "Target"=>$Member_Name,
12089 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012090 "Old_Value"=>$Member_Value1,
12091 "New_Value"=>$Member_Value2 );
12092 }
12093 }
12094 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12095 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012096 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12097 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12098
12099 if($Access1 ne "private"
12100 and $Access2 eq "private")
12101 {
12102 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12103 "Target"=>$Member_Name,
12104 "Type_Name"=>$Type1_Pure{"Name"});
12105 }
12106 elsif($Access1 ne "protected"
12107 and $Access1 ne "private"
12108 and $Access2 eq "protected")
12109 {
12110 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12111 "Target"=>$Member_Name,
12112 "Type_Name"=>$Type1_Pure{"Name"});
12113 }
12114
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012115 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12116 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012117 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012118 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12119 $SizeV1 = $BSize1;
12120 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012121 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012122 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12123 $SizeV2 = $BSize2;
12124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012125 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12126 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012127 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012128 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012129 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012130 {
12131 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12132 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12133 { # field size change (including anon-structures and unions)
12134 # - same types
12135 # - unnamed types
12136 # - bitfields
12137 my $ProblemType = "Field_Size";
12138 if(not isPublic(\%Type1_Pure, $Member_Pos)
12139 or isUnnamed($Member_Name))
12140 { # should not be accessed by applications, goes to "Low Severity"
12141 # example: "abidata" members in GStreamer types
12142 $ProblemType = "Private_".$ProblemType;
12143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012144 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 +040012145 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012146 if($Type2_Pure{"Type"} ne "Union"
12147 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012148 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012149 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 +040012150 { # changed offset
12151 $ProblemType .= "_And_Layout";
12152 }
12153 }
12154 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12155 $ProblemType .= "_And_Type_Size";
12156 }
12157 }
12158 if($ProblemType eq "Private_Field_Size")
12159 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012160 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012161 if($ProblemType eq "Field_Size")
12162 {
12163 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12164 { # Low severity
12165 $ProblemType = "Struct_Field_Size_Increased";
12166 }
12167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012168 if($ProblemType)
12169 { # register a problem
12170 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12171 "Target"=>$Member_Name,
12172 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012173 "Old_Size"=>$SizeV1,
12174 "New_Size"=>$SizeV2);
12175 }
12176 }
12177 }
12178 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12179 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12180 { # do NOT check bitfield type changes
12181 next;
12182 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012183 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012184 {
12185 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12186 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12187 {
12188 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12189 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012190 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012191 }
12192 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12193 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12194 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012195 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012196 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012197 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012198 }
12199 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012200 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12201 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012202 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012203 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12204 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012205
12206 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012208 or $ProblemType eq "Field_Type_And_Size"
12209 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012210 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012211 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012212 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012213 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012214 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012215 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012216 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012217 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012218 }
12219 }
12220 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12221 {
12222 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012223 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012224 }
12225 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012226 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012227 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012228 }
12229 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12230 {
12231 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012232 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012233 }
12234 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012235 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012236 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012237 }
12238 }
12239 }
12240
12241 if($Level eq "Source")
12242 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012243 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012244 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012245 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12246 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012247
12248 if($ProblemType eq "Field_Type")
12249 {
12250 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012251 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 }
12253 }
12254 }
12255 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012256
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012257 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 {
12259 my $ProblemType_Init = $ProblemType;
12260 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012261 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 if(not isPublic(\%Type1_Pure, $Member_Pos)
12263 or isUnnamed($Member_Name)) {
12264 $ProblemType = "Private_".$ProblemType;
12265 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012266 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 +040012267 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012268 if($Type2_Pure{"Type"} ne "Union"
12269 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012271 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 +040012272 { # changed offset
12273 $ProblemType .= "_And_Layout";
12274 }
12275 }
12276 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12277 $ProblemType .= "_And_Type_Size";
12278 }
12279 }
12280 }
12281 else
12282 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012283 # TODO: Private_Field_Type rule?
12284
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012285 if(not isPublic(\%Type1_Pure, $Member_Pos)
12286 or isUnnamed($Member_Name)) {
12287 next;
12288 }
12289 }
12290 if($ProblemType eq "Private_Field_Type_And_Size")
12291 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012292 }
12293 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12294 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012295 "Type_Name"=>$Type1_Pure{"Name"});
12296
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012297 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012299 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012300 }
12301 }
12302 if(not isPublic(\%Type1_Pure, $Member_Pos))
12303 { # do NOT check internal type changes
12304 next;
12305 }
12306 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012307 { # checking member type changes
12308 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12309
12310 my %DupProblems = ();
12311
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012312 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012314 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012315 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012316 if(not defined $AllAffected)
12317 {
12318 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12319 next;
12320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012321 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012322
12323 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12324 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12325
12326 if(not defined $AllAffected)
12327 {
12328 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012329 }
12330 }
12331 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012332
12333 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012334 }
12335 }
12336 }
12337 }
12338 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12339 { # checking added members, public and private
12340 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12341 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012342 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012343 if($AddedField{$Member_Pos})
12344 { # added
12345 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12346 {
12347 my $ProblemType = "Added_Field";
12348 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012349 or isUnnamed($Member_Name))
12350 {
12351 if($Level eq "Source") {
12352 next;
12353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012354 $ProblemType = "Added_Private_Field";
12355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012356 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012357 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 {
12359 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12360 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012361 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 +040012362 { # changed offset
12363 $ProblemType .= "_And_Layout";
12364 }
12365 }
12366 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12367 $ProblemType .= "_And_Size";
12368 }
12369 }
12370 if($ProblemType eq "Added_Private_Field")
12371 { # skip added private fields
12372 next;
12373 }
12374 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12375 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012376 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012377 }
12378 elsif($Type2_Pure{"Type"} eq "Union")
12379 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012380 if($Level eq "Binary"
12381 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382 {
12383 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12384 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012385 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 }
12387 else
12388 {
12389 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12390 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012391 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012392 }
12393 }
12394 elsif($Type2_Pure{"Type"} eq "Enum")
12395 {
12396 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12397 next if($Member_Value eq "");
12398 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12399 "Target"=>$Member_Name,
12400 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012401 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012402 }
12403 }
12404 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012405
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012406 if($Type1_Pure{"Type"} eq "FuncPtr")
12407 {
12408 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12409 {
12410 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12411 next;
12412 }
12413
12414 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12415 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12416
12417 my $PName = "p".$PPos;
12418
12419 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12420 my %DupProblems = ();
12421
12422 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12423 {
12424 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12425 {
12426 if(not defined $AllAffected)
12427 {
12428 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12429 next;
12430 }
12431 }
12432
12433 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12434 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12435
12436 if(not defined $AllAffected)
12437 {
12438 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12439 }
12440 }
12441 }
12442
12443 %DupProblems = ();
12444 }
12445 }
12446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012447 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012448 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449}
12450
12451sub isUnnamed($) {
12452 return $_[0]=~/\Aunnamed\d+\Z/;
12453}
12454
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012455sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012456{
12457 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012458 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12459 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12460 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12461 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012462 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012463 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012464 }
12465 return $TypeName;
12466}
12467
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012468sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012469{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012470 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012471 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012472 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12473 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12476 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012477 return () if(not $Type{"Type"});
12478 if($Type{"Type"} ne $Type_Type)
12479 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012480 return () if(not $Type{"BaseType"});
12481 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012482 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012483 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012484 return %Type;
12485}
12486
12487my %TypeSpecAttributes = (
12488 "Const" => 1,
12489 "Volatile" => 1,
12490 "ConstVolatile" => 1,
12491 "Restrict" => 1,
12492 "Typedef" => 1
12493);
12494
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012495sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012496{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012497 my ($TypeId, $Info) = @_;
12498 if(not $TypeId or not $Info
12499 or not $Info->{$TypeId}) {
12500 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012502 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12503 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12504 }
12505 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012506 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012507 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012508 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012510 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 return %Type;
12512}
12513
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012514sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12519 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012520 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012521 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12522 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012523 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12524 my $PLevel = 0;
12525 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12526 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012527 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012528 return $PLevel if(not $Type{"BaseType"});
12529 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12530 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12531 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532}
12533
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012534sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012535{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012536 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012537 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012538 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12539 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012541 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12542 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012543 return %Type if(not $Type{"BaseType"});
12544 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012545 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012546 return %Type;
12547}
12548
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012549sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012551 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012552 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012553 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12554 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012555 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556 my $Qual = "";
12557 if($Type{"Type"} eq "Pointer") {
12558 $Qual .= "*";
12559 }
12560 elsif($Type{"Type"} eq "Ref") {
12561 $Qual .= "&";
12562 }
12563 elsif($Type{"Type"} eq "ConstVolatile") {
12564 $Qual .= "const volatile";
12565 }
12566 elsif($Type{"Type"} eq "Const"
12567 or $Type{"Type"} eq "Volatile"
12568 or $Type{"Type"} eq "Restrict") {
12569 $Qual .= lc($Type{"Type"});
12570 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012571 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572 return $BQual.$Qual;
12573}
12574
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012575sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012577 my ($TypeId, $Info) = @_;
12578 if(not $TypeId or not $Info
12579 or not $Info->{$TypeId}) {
12580 return ();
12581 }
12582 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012583 return %Type if(not $Type{"BaseType"});
12584 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012585 {
12586 if($Info->{$BTid}) {
12587 return %{$Info->{$BTid}};
12588 }
12589 else { # something is going wrong
12590 return ();
12591 }
12592 }
12593 else {
12594 return %Type;
12595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012596}
12597
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012598sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012600 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012601 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012602 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12603 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604}
12605
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012606sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012607{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608 my $Symbol = $_[0];
12609 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12610}
12611
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012612sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012613 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12614}
12615
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012618 my ($SInfo, $LibVersion) = @_;
12619
12620 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012621 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012622 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012623 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012624 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012625 return 1;
12626 }
12627 }
12628 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012629 if(my $ShortName = $SInfo->{"ShortName"})
12630 {
12631 if(index($ShortName,"<")!=-1
12632 and index($ShortName,">")!=-1) {
12633 return 1;
12634 }
12635 }
12636
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012637 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012638}
12639
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012640sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012641{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012642 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012643 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012644 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012645 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012646 { # class specialization
12647 return 1;
12648 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012649 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012650 { # method specialization
12651 return 1;
12652 }
12653 }
12654 return 0;
12655}
12656
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012657sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012658{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012659 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012660
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012661 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 { # non-public global data
12663 return 0;
12664 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012665
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012666 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012667 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012668 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012669 }
12670
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012671 if($Symbol=~/\A_Z/)
12672 {
12673 if($Symbol=~/[CD][3-4]E/) {
12674 return 0;
12675 }
12676 }
12677
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012678 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012679 { # support for old ABI dumps in --headers-only mode
12680 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12681 {
12682 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012684 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012685 if(not $PType or $PType eq "Unknown") {
12686 return 0;
12687 }
12688 }
12689 }
12690 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012691 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012692 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012693 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012695 if($SkipSymbols{$LibVersion}{$Symbol})
12696 { # user defined symbols to ignore
12697 return 0;
12698 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012699
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012700 if($SymbolsListPath and not $SymbolsList{$Symbol})
12701 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012702 if(not $TargetHeadersPath or not $Header
12703 or not is_target_header($Header, 1))
12704 { # -symbols-list | -headers-list
12705 return 0;
12706 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012707 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012708
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012709 if($AppPath and not $SymbolsList_App{$Symbol})
12710 { # user defined symbols (in application)
12711 return 0;
12712 }
12713
12714 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12715
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012716 if($ClassId)
12717 {
12718 if(not isTargetType($ClassId, $LibVersion)) {
12719 return 0;
12720 }
12721 }
12722
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012723 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12724 if(not $NameSpace and $ClassId)
12725 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012726 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 }
12728 if($NameSpace)
12729 { # user defined namespaces to ignore
12730 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12731 return 0;
12732 }
12733 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12734 { # nested namespaces
12735 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12736 return 0;
12737 }
12738 }
12739 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012740 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012741 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012742 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012743 { # --skip-headers or <skip_headers> (not <skip_including>)
12744 if($Skip==1) {
12745 return 0;
12746 }
12747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012748 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012749 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012750 { # user defined types
12751 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12752
12753 if(not $TypesList{$CName})
12754 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012755 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12756 {
12757 $CName=~s/\A\Q$NS\E\:\://g;
12758 }
12759
12760 if(not $TypesList{$CName})
12761 {
12762 my $Found = 0;
12763
12764 while($CName=~s/\:\:.+?\Z//)
12765 {
12766 if($TypesList{$CName})
12767 {
12768 $Found = 1;
12769 last;
12770 }
12771 }
12772
12773 if(not $Found) {
12774 return 0;
12775 }
12776 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012777 }
12778 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012779
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012780 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12781 { # non-target symbols
12782 return 0;
12783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012784 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012785 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012786 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12787 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012789 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12790 { # inline virtual methods
12791 if($Type=~/InlineVirt/) {
12792 return 1;
12793 }
12794 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12795 if(not $Allocable)
12796 { # check bases
12797 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12798 {
12799 if(not isCopyingClass($DCId, $LibVersion))
12800 { # exists a derived class without default c-tor
12801 $Allocable=1;
12802 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012804 }
12805 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012806 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 return 0;
12808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012809 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012810 else
12811 { # inline non-virtual methods
12812 return 0;
12813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012815 }
12816 }
12817 return 1;
12818}
12819
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012820sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012821{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012822 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012823 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12824 {
12825 if(link_symbol($Symbol, 1, "+Deps"))
12826 { # linker can find a new symbol
12827 # in the old-version library
12828 # So, it's not a new symbol
12829 next;
12830 }
12831 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012832 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012833 next;
12834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012835 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012836 }
12837}
12838
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012841 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012842 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12843 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844 if(link_symbol($Symbol, 2, "+Deps"))
12845 { # linker can find an old symbol
12846 # in the new-version library
12847 next;
12848 }
12849 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012850 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012851 next;
12852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012853 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012854 }
12855}
12856
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012857sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012858{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 my $Level = $_[0];
12860 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012861 { # checking added symbols
12862 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012863 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012864 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012865 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012867 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012868 { # checking removed symbols
12869 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012870 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012871 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 { # skip v-tables for templates, that should not be imported by applications
12873 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012874 if(my $CName = $VTableClass{$Symbol})
12875 {
12876 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12877 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012878 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012879 next;
12880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012881 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012882
12883 if($SkipSymbols{1}{$Symbol})
12884 { # user defined symbols to ignore
12885 next;
12886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012887 }
12888 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012889 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 }
12891 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12892 { # symbols for pure virtual methods cannot be called by clients
12893 next;
12894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012895 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012896 }
12897}
12898
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012899sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012900{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012901 my ($LibVersion, $V) = @_;
12902 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12903 return $Cache{"checkDump"}{$LibVersion}{$V};
12904 }
12905 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012906}
12907
12908sub detectAdded_H($)
12909{
12910 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012911 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12912 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012913 if($Level eq "Source")
12914 { # remove symbol version
12915 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12916 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012917
12918 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12919 { # skip artificial constructors
12920 next;
12921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012922 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012923 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12924 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012925 next;
12926 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012927 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012928 next;
12929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012930 if(not defined $CompleteSignature{1}{$Symbol}
12931 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12932 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012933 if($UsedDump{2}{"SrcBin"})
12934 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012935 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012936 { # support for old and different (!) ABI dumps
12937 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12938 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012939 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012941 {
12942 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12943 {
12944 if($Lang eq "C")
12945 { # support for old ABI dumps: missed extern "C" functions
12946 next;
12947 }
12948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012949 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012950 else
12951 {
12952 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012953 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012954 next;
12955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012956 }
12957 }
12958 }
12959 }
12960 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012961 }
12962 }
12963}
12964
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012965sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012966{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012967 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012968 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12969 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012970 if($Level eq "Source")
12971 { # remove symbol version
12972 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12973 $Symbol=$SN;
12974 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012975 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12976 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012977 next;
12978 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012979 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012980 next;
12981 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 if(not defined $CompleteSignature{2}{$Symbol}
12983 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012984 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012985 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012987 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012988 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012989 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12990 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012991 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012992 if($CheckHeadersOnly)
12993 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012994 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12995 {
12996 if($Lang eq "C")
12997 { # support for old ABI dumps: missed extern "C" functions
12998 next;
12999 }
13000 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013001 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013002 else
13003 {
13004 if(not link_symbol($Symbol, 1, "-Deps"))
13005 { # skip removed inline symbols
13006 next;
13007 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013008 }
13009 }
13010 }
13011 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013012 if(not checkDump(1, "2.15"))
13013 {
13014 if($Symbol=~/_IT_E\Z/)
13015 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13016 next;
13017 }
13018 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013019 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13020 {
13021 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13022 {
13023 if(defined $Constants{2}{$Short})
13024 {
13025 my $Val = $Constants{2}{$Short}{"Value"};
13026 if(defined $Func_ShortName{2}{$Val})
13027 { # old name defined to new
13028 next;
13029 }
13030 }
13031 }
13032
13033 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013034 $RemovedInt{$Level}{$Symbol} = 1;
13035 if($Level eq "Source")
13036 { # search for a source-compatible equivalent
13037 setAlternative($Symbol, $Level);
13038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013039 }
13040 }
13041}
13042
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013043sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013045 my $Level = $_[0];
13046 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013047 { # checking added symbols
13048 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013049 next if($CompleteSignature{2}{$Symbol}{"Private"});
13050 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013051 if($Level eq "Binary")
13052 {
13053 if($CompleteSignature{2}{$Symbol}{"InLine"})
13054 {
13055 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13056 { # skip inline non-virtual functions
13057 next;
13058 }
13059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013060 }
13061 else
13062 { # Source
13063 if($SourceAlternative_B{$Symbol}) {
13064 next;
13065 }
13066 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013067 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013068 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013069 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013070 { # checking removed symbols
13071 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013072 next if($CompleteSignature{1}{$Symbol}{"Private"});
13073 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013074 if($Level eq "Binary")
13075 {
13076 if($CompleteSignature{1}{$Symbol}{"InLine"})
13077 {
13078 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13079 { # skip inline non-virtual functions
13080 next;
13081 }
13082 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013083 }
13084 else
13085 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013086 if(my $Alt = $SourceAlternative{$Symbol})
13087 {
13088 if(defined $CompleteSignature{1}{$Alt}
13089 and $CompleteSignature{1}{$Symbol}{"Const"})
13090 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013091 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013092 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013093 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013094 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013095 }
13096 else
13097 { # do NOT show removed symbol
13098 next;
13099 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013100 }
13101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013102 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013103 }
13104}
13105
13106sub addParamNames($)
13107{
13108 my $LibraryVersion = $_[0];
13109 return if(not keys(%AddIntParams));
13110 my $SecondVersion = $LibraryVersion==1?2:1;
13111 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13112 {
13113 next if(not keys(%{$AddIntParams{$Interface}}));
13114 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013115 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013116 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13117 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013118 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013119 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13120 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13121 {
13122 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13123 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13124 }
13125 }
13126 else {
13127 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13128 }
13129 }
13130 }
13131 }
13132}
13133
13134sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013135{ # detect changed typedefs to show
13136 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013137 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13138 {
13139 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013140 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13141 if(not $BName1 or isAnon($BName1)) {
13142 next;
13143 }
13144 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13145 if(not $BName2 or isAnon($BName2)) {
13146 next;
13147 }
13148 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013149 $ChangedTypedef{$Typedef} = 1;
13150 }
13151 }
13152}
13153
13154sub get_symbol_suffix($$)
13155{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 my ($Symbol, $Full) = @_;
13157 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013158 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013159 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013160 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013161 if(not $Full) {
13162 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13163 }
13164 return $Suffix;
13165}
13166
13167sub get_symbol_prefix($$)
13168{
13169 my ($Symbol, $LibVersion) = @_;
13170 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13171 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13172 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013173 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174 }
13175 return $ShortName;
13176}
13177
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013179{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 my $Symbol = $_[0];
13181 my $PSymbol = $Symbol;
13182 if(not defined $CompleteSignature{2}{$PSymbol}
13183 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13184 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13185 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013186 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013187 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013188 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013190 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13191 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 {
13193 if(defined $CompleteSignature{2}{$PSymbol}
13194 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13195 {
13196 $SourceAlternative{$Symbol} = $PSymbol;
13197 $SourceAlternative_B{$PSymbol} = $Symbol;
13198 if(not defined $CompleteSignature{1}{$PSymbol}
13199 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13200 $SourceReplacement{$Symbol} = $PSymbol;
13201 }
13202 }
13203 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013204 }
13205 else
13206 {
13207 foreach my $Sp ("KV", "VK", "K", "V")
13208 {
13209 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13210 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13211 {
13212 if(defined $CompleteSignature{2}{$PSymbol}
13213 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13214 {
13215 $SourceAlternative{$Symbol} = $PSymbol;
13216 $SourceAlternative_B{$PSymbol} = $Symbol;
13217 if(not defined $CompleteSignature{1}{$PSymbol}
13218 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13219 $SourceReplacement{$Symbol} = $PSymbol;
13220 }
13221 }
13222 }
13223 $PSymbol = $Symbol;
13224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013225 }
13226 }
13227 }
13228 return "";
13229}
13230
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013231sub getSymKind($$)
13232{
13233 my ($Symbol, $LibVersion) = @_;
13234 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13235 {
13236 return "Global_Data";
13237 }
13238 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13239 {
13240 return "Method";
13241 }
13242 return "Function";
13243}
13244
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013245sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013246{
13247 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013248 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013249
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 mergeBases($Level);
13251
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013253 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013254 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013255 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 next;
13257 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013258 if(defined $CompleteSignature{1}{$Symbol}
13259 and $CompleteSignature{1}{$Symbol}{"Header"})
13260 { # double-check added symbol
13261 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013263 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 next;
13265 }
13266 if($Symbol=~/\A(_Z|\?)/)
13267 { # C++
13268 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13269 }
13270 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13271 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013272 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13273 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013274 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013275 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013276 {
13277 if($TName_Tid{1}{$AffectedClass_Name})
13278 { # class should exist in previous version
13279 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13280 { # old v-table is NOT copied by old applications
13281 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13282 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013283 "Target"=>get_Signature($Symbol, 2),
13284 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013285 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013288 }
13289 }
13290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013291 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13292 { # check all removed exported symbols
13293 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013294 next;
13295 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013296 if(defined $CompleteSignature{2}{$Symbol}
13297 and $CompleteSignature{2}{$Symbol}{"Header"})
13298 { # double-check removed symbol
13299 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013300 }
13301 if($CompleteSignature{1}{$Symbol}{"Private"})
13302 { # skip private methods
13303 next;
13304 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013305 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013306 next;
13307 }
13308 $CheckedSymbols{$Level}{$Symbol} = 1;
13309 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13310 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013311 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13312 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013313 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013314 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13315 {
13316 if($TName_Tid{2}{$AffectedClass_Name})
13317 { # class should exist in newer version
13318 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13319 { # old v-table is NOT copied by old applications
13320 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13321 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013322 "Target"=>get_Signature($OverriddenMethod, 1),
13323 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013324 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 }
13328 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013330 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013331 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013332 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013333 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013334 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013335 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013336 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013338 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013339 {
13340 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13341 "Target"=>$tr_name{$Symbol},
13342 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 else
13346 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013347 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 "Target"=>$tr_name{$Symbol},
13349 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
13352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013355 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 {
13357 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13358 "Target"=>$tr_name{$Symbol},
13359 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 else
13363 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013364 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013365 "Target"=>$tr_name{$Symbol},
13366 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 }
13369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013370 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13371 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13372 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13373 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13374 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013375 {
13376 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013377 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013378 $ProblemType = "Global_Data_Symbol_Changed_Type";
13379 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013380 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13381 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013382 "Old_Type"=>$RTName1,
13383 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013385 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013386 }
13387 }
13388 }
13389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013390 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013394 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013396 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13398 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013399 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013400 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013402 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 }
13404 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13406 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013407 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013408 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013410 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 }
13412 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013413 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013414 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013415 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013416 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013417 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013418 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013419 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013420 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013421 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013422 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013423 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013425 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013427 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013428 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013429 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013430 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013432 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013435 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013438 { # "volatile" to non-"volatile"
13439
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013440 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013441 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013442 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013444 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013445 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013446 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013447 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013448 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013449 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013451 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013452 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013453 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013455 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013456 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013457 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13458 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013459 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013461 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 }
13463 }
13464 }
13465 }
13466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013467 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13468 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013469 $CurrentSymbol = $Symbol;
13470
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013471 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13472 if($Level eq "Source")
13473 { # remove symbol version
13474 $Symbol=$SN;
13475 }
13476 else
13477 { # Binary
13478 if(not $SV)
13479 { # symbol without version
13480 if(my $VSym = $SymVer{1}{$Symbol})
13481 { # the symbol is linked with versioned symbol
13482 if($CompleteSignature{2}{$VSym}{"MnglName"})
13483 { # show report for symbol@ver only
13484 next;
13485 }
13486 elsif(not link_symbol($VSym, 2, "-Deps"))
13487 { # changed version: sym@v1 to sym@v2
13488 # do NOT show report for symbol
13489 next;
13490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013491 }
13492 }
13493 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013494 my $PSymbol = $Symbol;
13495 if($Level eq "Source"
13496 and my $S = $SourceReplacement{$Symbol})
13497 { # take a source-compatible replacement function
13498 $PSymbol = $S;
13499 }
13500 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013501 { # private symbols
13502 next;
13503 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013504 if(not defined $CompleteSignature{1}{$Symbol}
13505 or not defined $CompleteSignature{2}{$PSymbol})
13506 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013507 next;
13508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013509 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13510 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13511 { # no mangled name
13512 next;
13513 }
13514 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13515 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013516 { # without a header
13517 next;
13518 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013519
13520 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13521 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13522 { # became pure
13523 next;
13524 }
13525 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13526 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13527 { # became non-pure
13528 next;
13529 }
13530
13531 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13532 { # exported, target, inline virtual and pure virtual
13533 next;
13534 }
13535 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13536 { # exported, target, inline virtual and pure virtual
13537 next;
13538 }
13539
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013540 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013541 {
13542 if($CompleteSignature{1}{$Symbol}{"Data"}
13543 and $CompleteSignature{2}{$PSymbol}{"Data"})
13544 {
13545 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13546 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13547 if(defined $Value1)
13548 {
13549 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13550 if(defined $Value2)
13551 {
13552 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13553 if($Value1 ne $Value2)
13554 {
13555 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13556 "Old_Value"=>$Value1,
13557 "New_Value"=>$Value2,
13558 "Target"=>get_Signature($Symbol, 1) );
13559 }
13560 }
13561 }
13562 }
13563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013564
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013565 if($CompleteSignature{2}{$PSymbol}{"Private"})
13566 {
13567 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13568 "Target"=>get_Signature_M($PSymbol, 2) );
13569 }
13570 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13571 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13572 {
13573 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13574 "Target"=>get_Signature_M($PSymbol, 2) );
13575 }
13576 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13577 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13578 {
13579 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13580 "Target"=>get_Signature_M($PSymbol, 2) );
13581 }
13582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013583 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013584 mergeVirtualTables($Symbol, $Level);
13585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013586 if($COMPILE_ERRORS)
13587 { # if some errors occurred at the compiling stage
13588 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013589 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013590 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 { # missed information about parameters in newer version
13592 next;
13593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013594 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013595 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013596 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 next;
13598 }
13599 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013600 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013603 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013605 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13606 "Target"=>get_Signature($Symbol, 1)
13607 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013609 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013610 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13611 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013612 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013613 "Target"=>get_Signature($Symbol, 1)
13614 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013616 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13617 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013619 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013620 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013621 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13622 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13623 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013625 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013626 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13627 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013628 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013629 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 my $ProblemType = "Virtual_Method_Position";
13631 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13632 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013634 if(isUsedClass($Class_Id, 1, $Level))
13635 {
13636 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013637 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013638 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013639 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13640 next;
13641 }
13642 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013643 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13645 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013646 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013647 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013648 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013650 }
13651 }
13652 }
13653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13655 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 { # do NOT check type changes in pure virtuals
13657 next;
13658 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013659 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 if($Symbol=~/\A(_Z|\?)/
13661 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013662 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013663 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013664 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013665 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 }
13667 }
13668 else
13669 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013670 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013672 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013673 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13674 last if($PType2_Name eq "...");
13675 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13676 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013677 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013678 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013679 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013680 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13681 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13683 $ParamPos_Prev = "lost";
13684 }
13685 }
13686 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013687 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 }
13689 if($ParamPos_Prev eq "lost")
13690 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013691 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013692 {
13693 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 $ProblemType = "Added_Unnamed_Parameter";
13696 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013697 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013698 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013699 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013700 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013701 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013702 }
13703 else
13704 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013705 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013706 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013707 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013708 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13709 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013710 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013711 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013712 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013713 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013714 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013715 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013716 "Param_Type"=>$PType2_Name,
13717 "Old_Value"=>$PName_Old,
13718 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013719 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013720 }
13721 }
13722 else
13723 {
13724 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013725 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013726 $ProblemType = "Added_Middle_Unnamed_Parameter";
13727 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013728 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013729 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013730 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013731 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013732 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013733 }
13734 }
13735 }
13736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013737 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013738 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013739 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013740 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013742 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013743 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013744 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013745 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013746 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13747 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013748 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013749 }
13750 }
13751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013752 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013753 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013754 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013755 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13756 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013757 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13758 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013759 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013760 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013761 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013762 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13763 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13765 $ParamPos_New = "lost";
13766 }
13767 }
13768 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013769 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 }
13771 if($ParamPos_New eq "lost")
13772 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013773 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013774 {
13775 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013776 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013777 $ProblemType = "Removed_Unnamed_Parameter";
13778 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013779 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013780 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013781 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013782 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013783 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013784 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013785 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013786 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013787 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013788 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013789 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013790 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013791 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013792 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013793 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013794 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013795 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013796 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013797 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013798 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013799 "Old_Value"=>$PName,
13800 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013801 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 }
13803 }
13804 else
13805 {
13806 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013807 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013808 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13809 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013810 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013811 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013812 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013813 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013814 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013815 }
13816 }
13817 }
13818 }
13819 }
13820 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013821 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13822 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013823 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013824
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013825 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013826 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013827 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13828 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013829 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013830
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013831 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013832 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013833 if($SubProblemType eq "Return_Type_And_Size") {
13834 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13835 }
13836 elsif($SubProblemType eq "Return_Type_Format") {
13837 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13838 }
13839 else {
13840 $ProblemTypes{"Global_Data_Type"} = 1;
13841 }
13842
13843 # quals
13844 if($SubProblemType eq "Return_Type"
13845 or $SubProblemType eq "Return_Type_And_Size"
13846 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013847 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013848 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13849 { # const to non-const
13850 if($RR==2) {
13851 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13852 }
13853 else {
13854 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13855 }
13856 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013857 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13859 { # non-const to const
13860 if($RA==2) {
13861 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13862 }
13863 else {
13864 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13865 }
13866 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013867 }
13868 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013869 }
13870 else
13871 {
13872 # quals
13873 if($SubProblemType eq "Return_Type"
13874 or $SubProblemType eq "Return_Type_And_Size"
13875 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013876 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013877 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013878 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013879 if(addedQual($Old_Value, $New_Value, "volatile"))
13880 {
13881 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13882 if($Level ne "Source"
13883 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13884 $ProblemTypes{"Return_Type"} = 1;
13885 }
13886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013887 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013888 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13889 {
13890 if($RA==2) {
13891 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13892 }
13893 else {
13894 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13895 }
13896 if($Level ne "Source"
13897 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13898 $ProblemTypes{"Return_Type"} = 1;
13899 }
13900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013901 }
13902 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013903 if($Level eq "Binary"
13904 and not $CompleteSignature{1}{$Symbol}{"Data"})
13905 {
13906 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13907 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13908 { # if one of the architectures is unknown
13909 # then set other arhitecture to unknown too
13910 ($Arch1, $Arch2) = ("unknown", "unknown");
13911 }
13912 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013913 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013914 {
13915 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13916 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13917 }
13918 else
13919 {
13920 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13921 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13922 }
13923
13924 if($SubProblemType eq "Return_Type_Became_Void")
13925 {
13926 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13927 { # parameters stack has been affected
13928 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013929 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013930 }
13931 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013932 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013933 }
13934 }
13935 }
13936 elsif($SubProblemType eq "Return_Type_From_Void")
13937 {
13938 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13939 { # parameters stack has been affected
13940 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013941 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013942 }
13943 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013944 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013945 }
13946 }
13947 }
13948 elsif($SubProblemType eq "Return_Type"
13949 or $SubProblemType eq "Return_Type_And_Size"
13950 or $SubProblemType eq "Return_Type_Format")
13951 {
13952 if($Conv1{"Method"} ne $Conv2{"Method"})
13953 {
13954 if($Conv1{"Method"} eq "stack")
13955 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013956 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013957 }
13958 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013959 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013960 }
13961 }
13962 else
13963 {
13964 if($Conv1{"Method"} eq "reg")
13965 {
13966 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13967 {
13968 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013969 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013970 }
13971 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013972 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013973 }
13974 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013975 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013976 }
13977 }
13978 }
13979 }
13980 }
13981 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013982
13983 if(not keys(%ProblemTypes))
13984 { # default
13985 $ProblemTypes{$SubProblemType} = 1;
13986 }
13987
13988 foreach my $ProblemType (keys(%ProblemTypes))
13989 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013990 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013992 }
13993 if($ReturnType1_Id and $ReturnType2_Id)
13994 {
13995 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013996 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13997
13998 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013999
14000 if($CompleteSignature{1}{$Symbol}{"Data"})
14001 {
14002 if($Level eq "Binary")
14003 {
14004 if(get_PLevel($ReturnType1_Id, 1)==0)
14005 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014006 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014007 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014008
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014009 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14010 {
14011 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014012 {
14013 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14014 {
14015 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14016 last;
14017 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014019 }
14020 }
14021 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014022 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014023 {
14024 if(defined $GlobalDataObject{1}{$Symbol}
14025 and defined $GlobalDataObject{2}{$Symbol})
14026 {
14027 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14028 my $New_Size = $GlobalDataObject{2}{$Symbol};
14029 if($Old_Size!=$New_Size)
14030 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014031 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014032 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014033 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014034 }
14035 }
14036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014037 }
14038 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014039
14040 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014041 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014042 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014043 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014044 my $NewLocation = "retval";
14045 if($SubLocation and $SubLocation ne "retval") {
14046 $NewLocation = "retval->".$SubLocation;
14047 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014048 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14049 }
14050 }
14051
14052 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14053 {
14054 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14055 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014056 my $NewLocation = "retval";
14057 if($SubLocation and $SubLocation ne "retval") {
14058 $NewLocation = "retval->".$SubLocation;
14059 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014060 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014061 }
14062 }
14063 }
14064
14065 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014066 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14067 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14068 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014069 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014070 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014071 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14072 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014073 if($ThisPtr1_Id and $ThisPtr2_Id)
14074 {
14075 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014076 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14077 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014078 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014079 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014080 {
14081 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014082 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014083 }
14084 }
14085 }
14086 }
14087 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014088 if($Level eq "Binary") {
14089 mergeVTables($Level);
14090 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014091 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14092 $CheckedSymbols{$Level}{$Symbol} = 1;
14093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014094}
14095
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014096sub rmQuals($$)
14097{
14098 my ($Value, $Qual) = @_;
14099 if(not $Qual) {
14100 return $Value;
14101 }
14102 if($Qual eq "all")
14103 { # all quals
14104 $Qual = "const|volatile|restrict";
14105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014106 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014107 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014108 }
14109 return $Value;
14110}
14111
14112sub cmpBTypes($$$$)
14113{
14114 my ($T1, $T2, $V1, $V2) = @_;
14115 $T1 = uncover_typedefs($T1, $V1);
14116 $T2 = uncover_typedefs($T2, $V2);
14117 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14118}
14119
14120sub addedQual($$$)
14121{
14122 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014123 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014124}
14125
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014126sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014127{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014128 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014129 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014130}
14131
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014132sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014133{
14134 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14135 $Old_Value = uncover_typedefs($Old_Value, $V1);
14136 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014137
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014138 if($Old_Value eq $New_Value)
14139 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014140 return 0;
14141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014142 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143 { # without a qual
14144 return 0;
14145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014146 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014147 { # became non-qual
14148 return 1;
14149 }
14150 else
14151 {
14152 my @BQ1 = getQualModel($Old_Value, $Qual);
14153 my @BQ2 = getQualModel($New_Value, $Qual);
14154 foreach (0 .. $#BQ1)
14155 { # removed qual
14156 if($BQ1[$_]==1
14157 and $BQ2[$_]!=1)
14158 {
14159 return 2;
14160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014161 }
14162 }
14163 return 0;
14164}
14165
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014166sub getQualModel($$)
14167{
14168 my ($Value, $Qual) = @_;
14169 if(not $Qual) {
14170 return $Value;
14171 }
14172
14173 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014174 while($Value=~/(\w+)/)
14175 {
14176 my $W = $1;
14177
14178 if($W eq $Qual) {
14179 $Value=~s/\b$W\b/\@/g;
14180 }
14181 else {
14182 $Value=~s/\b$W\b//g;
14183 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014184 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014185
14186 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014187 $Value=~s/[^\*\&\w]+//g;
14188
14189 # modeling
14190 # int*const*const == 011
14191 # int**const == 001
14192 my @Model = ();
14193 my @Elems = split(/[\*\&]/, $Value);
14194 if(not @Elems) {
14195 return (0);
14196 }
14197 foreach (@Elems)
14198 {
14199 if($_ eq $Qual) {
14200 push(@Model, 1);
14201 }
14202 else {
14203 push(@Model, 0);
14204 }
14205 }
14206
14207 return @Model;
14208}
14209
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014210my %StringTypes = map {$_=>1} (
14211 "char*",
14212 "char const*"
14213);
14214
14215my %CharTypes = map {$_=>1} (
14216 "char",
14217 "char const"
14218);
14219
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014220sub showVal($$$)
14221{
14222 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014223 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014224 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014225 if(substr($Value, 0, 2) eq "_Z")
14226 {
14227 if(my $Unmangled = $tr_name{$Value}) {
14228 return $Unmangled;
14229 }
14230 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014231 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014232 { # strings
14233 return "\"$Value\"";
14234 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014235 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014236 { # characters
14237 return "\'$Value\'";
14238 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014239 if($Value eq "")
14240 { # other
14241 return "\'\'";
14242 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014243 return $Value;
14244}
14245
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014246sub getRegs($$$)
14247{
14248 my ($LibVersion, $Symbol, $Pos) = @_;
14249
14250 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14251 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014252 my %Regs = ();
14253 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14254 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014255 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014256 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14257 }
14258 }
14259
14260 return join(", ", sort keys(%Regs));
14261 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014262 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14263 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14264 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14265 {
14266 return "unknown";
14267 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014268
14269 return undef;
14270}
14271
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014272sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014273{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014274 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014275 if(not $Symbol) {
14276 return;
14277 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014278 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14279 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14280 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14281 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014282 if(not $PType1_Id
14283 or not $PType2_Id) {
14284 return;
14285 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014286
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014287 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014288 { # do not merge "this"
14289 if($PName1 eq "this" or $PName2 eq "this") {
14290 return;
14291 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014292 }
14293
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014294 my %Type1 = get_Type($PType1_Id, 1);
14295 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014296
14297 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14298
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014299 my %BaseType1 = get_BaseType($PType1_Id, 1);
14300 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014301
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014302 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014303
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014304 if($Level eq "Binary")
14305 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014306 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014307 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14308 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14309 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14310 {
14311 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014312 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014313 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014314 }
14315 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14316 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14317 {
14318 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014319 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014320 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014322 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014323
14324 if(defined $UsedDump{1}{"DWARF"}
14325 and defined $UsedDump{2}{"DWARF"})
14326 {
14327 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14328 {
14329 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14330 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014331
14332 if($Old_Regs ne "unknown"
14333 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014334 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014335 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014336 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014337 if($Old_Regs ne $New_Regs)
14338 {
14339 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14340 "Target"=>$PName1,
14341 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14342 "Old_Value"=>$Old_Regs,
14343 "New_Value"=>$New_Regs );
14344 }
14345 }
14346 elsif($Old_Regs and not $New_Regs)
14347 {
14348 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014349 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014350 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014351 "Old_Value"=>$Old_Regs );
14352 }
14353 elsif(not $Old_Regs and $New_Regs)
14354 {
14355 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14356 "Target"=>$PName1,
14357 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014358 "New_Value"=>$New_Regs );
14359 }
14360 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014361
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014362 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14363 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14364 {
14365 if($Old_Offset ne $New_Offset)
14366 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014367 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14368 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14369
14370 $Old_Offset = $Old_Offset - $Start1;
14371 $New_Offset = $New_Offset - $Start2;
14372
14373 if($Old_Offset ne $New_Offset)
14374 {
14375 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14376 "Target"=>$PName1,
14377 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14378 "Old_Value"=>$Old_Offset,
14379 "New_Value"=>$New_Offset );
14380 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014381 }
14382 }
14383 }
14384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014385 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014386 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14387 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014388 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014389 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014390 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14391 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014392 if(not checkDump(1, "2.13")
14393 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014394 { # support for old ABI dumps
14395 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014397 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014398 and $Value_Old eq "false" and $Value_New eq "0")
14399 { # int class::method ( bool p = 0 );
14400 # old ABI dumps: "false"
14401 # new ABI dumps: "0"
14402 $Value_Old = "0";
14403 }
14404 }
14405 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014406 if(not checkDump(1, "2.18")
14407 and checkDump(2, "2.18"))
14408 { # support for old ABI dumps
14409 if(not defined $Value_Old
14410 and substr($Value_New, 0, 2) eq "_Z") {
14411 $Value_Old = $Value_New;
14412 }
14413 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014414 if(defined $Value_Old)
14415 {
14416 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14417 if(defined $Value_New)
14418 {
14419 $Value_New = showVal($Value_New, $PType2_Id, 2);
14420 if($Value_Old ne $Value_New)
14421 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014422 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014423 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014424 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014425 "Old_Value"=>$Value_Old,
14426 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014427 }
14428 }
14429 else
14430 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014431 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014432 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014433 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014434 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014435 }
14436 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014437 elsif(defined $Value_New)
14438 {
14439 $Value_New = showVal($Value_New, $PType2_Id, 2);
14440 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14441 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014442 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014443 "New_Value"=>$Value_New );
14444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014445 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014446
14447 if($ChkRnmd)
14448 {
14449 if($PName1 and $PName2 and $PName1 ne $PName2
14450 and $PType1_Id!=-1 and $PType2_Id!=-1
14451 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14452 { # except unnamed "..." value list (Id=-1)
14453 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14454 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014455 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014456 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14457 "Old_Value"=>$PName1,
14458 "New_Value"=>$PName2,
14459 "New_Signature"=>get_Signature($Symbol, 2) );
14460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014461 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014463 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014464 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014466 foreach my $SubProblemType (keys(%SubProblems))
14467 { # add new problems, remove false alarms
14468 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14469 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014470
14471 # quals
14472 if($SubProblemType eq "Parameter_Type"
14473 or $SubProblemType eq "Parameter_Type_And_Size"
14474 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014476 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014477 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014478 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014479 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014480 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014481 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14482 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14483 }
14484 }
14485 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14486 {
14487 if(removedQual($Old_Value, $New_Value, "volatile")) {
14488 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 }
14490 }
14491 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14492 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14493 { # int to "int const"
14494 delete($SubProblems{$SubProblemType});
14495 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014496 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014497 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14498 { # "int const" to int
14499 delete($SubProblems{$SubProblemType});
14500 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014501 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14502 { # "const" to non-"const"
14503 if($RR==2) {
14504 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14505 }
14506 else {
14507 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14508 }
14509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 }
14511 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014512
14513 if($Level eq "Source")
14514 {
14515 foreach my $SubProblemType (keys(%SubProblems))
14516 {
14517 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14518 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14519
14520 if($SubProblemType eq "Parameter_Type")
14521 {
14522 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14523 delete($SubProblems{$SubProblemType});
14524 }
14525 }
14526 }
14527 }
14528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014529 foreach my $SubProblemType (keys(%SubProblems))
14530 { # modify/register problems
14531 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14532 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014533 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14534 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014535
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 my $NewProblemType = $SubProblemType;
14537 if($Old_Value eq "..." and $New_Value ne "...")
14538 { # change from "..." to "int"
14539 if($ParamPos1==0)
14540 { # ISO C requires a named argument before "..."
14541 next;
14542 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014543 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014544 }
14545 elsif($New_Value eq "..." and $Old_Value ne "...")
14546 { # change from "int" to "..."
14547 if($ParamPos2==0)
14548 { # ISO C requires a named argument before "..."
14549 next;
14550 }
14551 $NewProblemType = "Parameter_Became_VaList";
14552 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014553 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014554 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 {
14556 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014557 if($Arch1 eq "unknown"
14558 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014559 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014560 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014561 ($Arch1, $Arch2) = ("unknown", "unknown");
14562 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014563 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014564 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014565 { # real
14566 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14567 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14568 }
14569 else
14570 { # model
14571 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14572 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14573 }
14574 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014575 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014576 if($Conv1{"Method"} eq "stack")
14577 {
14578 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14579 $NewProblemType = "Parameter_Type_And_Stack";
14580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014581 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014582 elsif($Conv1{"Method"} eq "reg")
14583 {
14584 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14585 $NewProblemType = "Parameter_Type_And_Register";
14586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014587 }
14588 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014589 elsif($Conv1{"Method"} ne "unknown"
14590 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014591 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014592 if($Conv1{"Method"} eq "stack") {
14593 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014594 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014595 elsif($Conv1{"Method"} eq "register") {
14596 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014597 }
14598 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014599 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14600 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014602 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014603 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014604 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014605 "New_Signature"=>get_Signature($Symbol, 2) );
14606 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014607 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014609 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014611 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014612 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14613 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014615 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616 {
14617 my $NewProblemType = $SubProblemType;
14618 if($SubProblemType eq "DataType_Size")
14619 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014620 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 { # stack has been affected
14622 $NewProblemType = "DataType_Size_And_Stack";
14623 }
14624 }
14625 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014626 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 }
14628 }
14629}
14630
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631sub find_ParamPair_Pos_byName($$$)
14632{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014633 my ($Name, $Symbol, $LibVersion) = @_;
14634 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014636 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14637 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014638 {
14639 return $ParamPos;
14640 }
14641 }
14642 return "lost";
14643}
14644
14645sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14646{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014647 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014648 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014649 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014650 {
14651 next if($Order eq "backward" and $ParamPos>$MediumPos);
14652 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014653 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14654 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014655 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014656 push(@Positions, $ParamPos);
14657 }
14658 }
14659 return @Positions;
14660}
14661
14662sub getTypeIdByName($$)
14663{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014664 my ($TypeName, $LibVersion) = @_;
14665 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014666}
14667
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014668sub diffTypes($$$)
14669{
14670 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14671 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14672 }
14673 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14674 { # skip recursive declarations
14675 return 0;
14676 }
14677
14678 pushType($_[0], $_[1], \@RecurTypes_Diff);
14679 my $Diff = diffTypes_I(@_);
14680 pop(@RecurTypes_Diff);
14681
14682 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14683}
14684
14685sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014687 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014688
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014689 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14690 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14693 { # equal types
14694 return 0;
14695 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014696 if($Type1_Pure{"Name"} eq "void")
14697 { # from void* to something
14698 return 0;
14699 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014700 if($Type2_Pure{"Name"} eq "void")
14701 { # from something to void*
14702 return 0;
14703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014704 if($Type1_Pure{"Name"}=~/\*/
14705 or $Type2_Pure{"Name"}=~/\*/)
14706 { # compared in detectTypeChange()
14707 return 0;
14708 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014709
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710 my %FloatType = map {$_=>1} (
14711 "float",
14712 "double",
14713 "long double"
14714 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014715
14716 my $T1 = $Type1_Pure{"Type"};
14717 my $T2 = $Type2_Pure{"Type"};
14718
14719 if($T1 eq "Struct"
14720 and $T2 eq "Class")
14721 { # compare as data structures
14722 $T2 = "Struct";
14723 }
14724
14725 if($T1 eq "Class"
14726 and $T2 eq "Struct")
14727 { # compare as data structures
14728 $T1 = "Struct";
14729 }
14730
14731 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014732 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014733 if($T1 eq "Intrinsic"
14734 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 { # "int" to "enum"
14736 return 0;
14737 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014738 elsif($T2 eq "Intrinsic"
14739 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014740 { # "enum" to "int"
14741 return 0;
14742 }
14743 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014744 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 # ...
14746 return 1;
14747 }
14748 }
14749 else
14750 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014751 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 {
14753 if($FloatType{$Type1_Pure{"Name"}}
14754 or $FloatType{$Type2_Pure{"Name"}})
14755 { # "float" to "double"
14756 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014757 if($Level eq "Source")
14758 { # Safe
14759 return 0;
14760 }
14761 else {
14762 return 1;
14763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014764 }
14765 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014766 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014767 {
14768 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14769 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014770 if(not @Membs1
14771 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014772 { # private
14773 return 0;
14774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014775 if($#Membs1!=$#Membs2)
14776 { # different number of elements
14777 return 1;
14778 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014779 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014780 {
14781 foreach my $Pos (@Membs1)
14782 { # compare elements by name and value
14783 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14784 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14785 { # different names
14786 return 1;
14787 }
14788 }
14789 }
14790 else
14791 {
14792 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014793 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014794 if($Level eq "Source")
14795 {
14796 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14797 { # different names
14798 return 1;
14799 }
14800 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014801
14802 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14803 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14804
14805 if($MT1{"Name"} ne $MT2{"Name"}
14806 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14807 {
14808 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14809 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14810
14811 if($PL1 ne $PL2)
14812 { # different pointer level
14813 return 1;
14814 }
14815
14816 # compare base types
14817 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14818 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14819
14820 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14821 { # different types
14822 return 1;
14823 }
14824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014825 }
14826 }
14827 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014828 else
14829 {
14830 # TODO: arrays, etc.
14831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014832 }
14833 return 0;
14834}
14835
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014836sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014837{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014838 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014839 if(not $Type1_Id or not $Type2_Id) {
14840 return ();
14841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014842 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014843 my %Type1 = get_Type($Type1_Id, 1);
14844 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014845 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14846 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014847
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014848 if(defined $SkipTypedefUncover)
14849 {
14850 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14851 return ();
14852 }
14853
14854 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14855 return ();
14856 }
14857 }
14858
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014859 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14860 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 +040014861
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014862 if(defined $UsedDump{1}{"DWARF"})
14863 {
14864 if($Type1_Pure{"Name"} eq "__unknown__"
14865 or $Type2_Pure{"Name"} eq "__unknown__"
14866 or $Type1_Base{"Name"} eq "__unknown__"
14867 or $Type2_Base{"Name"} eq "__unknown__")
14868 { # Error ABI dump
14869 return ();
14870 }
14871 }
14872
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014873 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14874 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014875 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14876 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14877 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14878 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14879 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14880 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14881 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014882 if($Type1{"Name"} eq $Type2{"Name"})
14883 {
14884 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14885 { # will be reported in mergeTypes() as typedef problem
14886 return ();
14887 }
14888 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14889 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14890 if(%Typedef_1 and %Typedef_2)
14891 {
14892 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14893 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14894 { # const Typedef
14895 return ();
14896 }
14897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014898 }
14899 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14900 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014901 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014902 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14903 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 {
14905 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14906 "Old_Value"=>$Type1_Base{"Name"},
14907 "New_Value"=>$Type2_Base{"Name"},
14908 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014909 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910 }
14911 else
14912 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014913 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014914 { # format change
14915 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14916 "Old_Value"=>$Type1_Base{"Name"},
14917 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014918 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014919 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 }
14921 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14922 {
14923 %{$LocalProblems{$Prefix."_BaseType"}}=(
14924 "Old_Value"=>$Type1_Base{"Name"},
14925 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014926 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014927 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014928 }
14929 }
14930 }
14931 }
14932 elsif($Type1{"Name"} ne $Type2{"Name"})
14933 { # type change
14934 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14935 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014936 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 and $Type1_Pure{"Name"} eq "void")
14938 {
14939 %{$LocalProblems{"Return_Type_From_Void"}}=(
14940 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014941 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014943 elsif($Prefix eq "Return"
14944 and $Type2_Pure{"Name"} eq "void")
14945 {
14946 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14947 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014948 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014950 else
14951 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014952 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014953 and $Type1{"Size"} and $Type2{"Size"}
14954 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 {
14956 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14957 "Old_Value"=>$Type1{"Name"},
14958 "New_Value"=>$Type2{"Name"},
14959 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014960 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014961 }
14962 else
14963 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014964 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014965 { # format change
14966 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14967 "Old_Value"=>$Type1{"Name"},
14968 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014969 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014970 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014971 }
14972 elsif(tNameLock($Type1_Id, $Type2_Id))
14973 { # FIXME: correct this condition
14974 %{$LocalProblems{$Prefix."_Type"}}=(
14975 "Old_Value"=>$Type1{"Name"},
14976 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014977 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014978 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 }
14980 }
14981 }
14982 }
14983 }
14984 if($Type1_PLevel!=$Type2_PLevel)
14985 {
14986 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14987 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14988 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014989 if($Level eq "Source")
14990 {
14991 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 "Old_Value"=>$Type1_PLevel,
14993 "New_Value"=>$Type2_PLevel);
14994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014995 else
14996 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014997 if($Type2_PLevel>$Type1_PLevel)
14998 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014999 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
15000 "Old_Value"=>$Type1_PLevel,
15001 "New_Value"=>$Type2_PLevel);
15002 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015003 else
15004 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015005 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
15006 "Old_Value"=>$Type1_PLevel,
15007 "New_Value"=>$Type2_PLevel);
15008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 }
15010 }
15011 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040015012 if($Type1_Pure{"Type"} eq "Array"
15013 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015014 { # base_type[N] -> base_type[N]
15015 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015016 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015017 foreach my $SubProblemType (keys(%SubProblems))
15018 {
15019 $SubProblemType=~s/_Type/_BaseType/g;
15020 next if(defined $LocalProblems{$SubProblemType});
15021 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
15022 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
15023 }
15024 }
15025 }
15026 return %LocalProblems;
15027}
15028
15029sub tNameLock($$)
15030{
15031 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015032 my $Changed = 0;
15033 if(differentDumps("G"))
15034 { # different GCC versions
15035 $Changed = 1;
15036 }
15037 elsif(differentDumps("V"))
15038 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015039 if(not checkDump(1, "2.20")
15040 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015041 { # latest names update
15042 # 2.6: added restrict qualifier
15043 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015044 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015045 $Changed = 1;
15046 }
15047 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015048
15049 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15050 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15051
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015052 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15053 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15054
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015055 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015056 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015057 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015058 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015059 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015061 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015062 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015063 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015064 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015065 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15066 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15067 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015068 { # equal base types
15069 return 0;
15070 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015071
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015072 if(not checkDump(1, "2.13")
15073 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015074 { # broken array names in ABI dumps < 2.13
15075 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015076 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015077 return 0;
15078 }
15079 }
15080
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015081 if(not checkDump(1, "2.6")
15082 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015083 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015084 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015085 and $TN2=~/\brestrict\b/) {
15086 return 0;
15087 }
15088 }
15089
15090 if(not checkDump(1, "2.20")
15091 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015092 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015093 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15094 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015095 return 0;
15096 }
15097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015098 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015099 else
15100 {
15101 # typedef struct {...} type_t
15102 # typedef struct type_t {...} type_t
15103 if(index($TN1, " ".$TN2)!=-1)
15104 {
15105 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15106 return 0;
15107 }
15108 }
15109 if(index($TN2, " ".$TN1)!=-1)
15110 {
15111 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15112 return 0;
15113 }
15114 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015115
15116 if($TT1 eq "FuncPtr"
15117 and $TT2 eq "FuncPtr")
15118 {
15119 my $TN1_C = $TN1;
15120 my $TN2_C = $TN2;
15121
15122 $TN1_C=~s/\b(struct|union) //g;
15123 $TN2_C=~s/\b(struct|union) //g;
15124
15125 if($TN1_C eq $TN2_C) {
15126 return 0;
15127 }
15128 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015129 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015130
15131 my ($N1, $N2) = ($TN1, $TN2);
15132 $N1=~s/\b(struct|union) //g;
15133 $N2=~s/\b(struct|union) //g;
15134
15135 if($N1 eq $N2)
15136 { # QList<struct QUrl> and QList<QUrl>
15137 return 0;
15138 }
15139
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015140 return 1;
15141}
15142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015143sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015144{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015145 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015146 if(defined $Cache{"differentDumps"}{$Check}) {
15147 return $Cache{"differentDumps"}{$Check};
15148 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015149 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015150 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015151 if($Check eq "G")
15152 {
15153 if(getGccVersion(1) ne getGccVersion(2))
15154 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015155 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015156 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015158 if($Check eq "V")
15159 {
15160 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15161 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15162 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015163 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015167 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015168}
15169
15170sub formatVersion($$)
15171{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015172 my ($V, $Digits) = @_;
15173 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015174 return join(".", splice(@Elems, 0, $Digits));
15175}
15176
15177sub htmlSpecChars($)
15178{
15179 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015180 if(not $Str) {
15181 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015183 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15184 $Str=~s/</&lt;/g;
15185 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15186 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015187 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15188 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015190 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015191 $Str=~s/\n/<br\/>/g;
15192 $Str=~s/\"/&quot;/g;
15193 $Str=~s/\'/&#39;/g;
15194 return $Str;
15195}
15196
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015197sub xmlSpecChars($)
15198{
15199 my $Str = $_[0];
15200 if(not $Str) {
15201 return $Str;
15202 }
15203
15204 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15205 $Str=~s/</&lt;/g;
15206 $Str=~s/>/&gt;/g;
15207
15208 $Str=~s/\"/&quot;/g;
15209 $Str=~s/\'/&#39;/g;
15210
15211 return $Str;
15212}
15213
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015214sub xmlSpecChars_R($)
15215{
15216 my $Str = $_[0];
15217 if(not $Str) {
15218 return $Str;
15219 }
15220
15221 $Str=~s/&amp;/&/g;
15222 $Str=~s/&lt;/</g;
15223 $Str=~s/&gt;/>/g;
15224
15225 $Str=~s/&quot;/"/g;
15226 $Str=~s/&#39;/'/g;
15227
15228 return $Str;
15229}
15230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231sub black_name($)
15232{
15233 my $Name = $_[0];
15234 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15235}
15236
15237sub highLight_Signature($)
15238{
15239 my $Signature = $_[0];
15240 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15241}
15242
15243sub highLight_Signature_Italic_Color($)
15244{
15245 my $Signature = $_[0];
15246 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15247}
15248
15249sub separate_symbol($)
15250{
15251 my $Symbol = $_[0];
15252 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15253 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15254 ($Name, $Spec, $Ver) = ($1, $2, $3);
15255 }
15256 return ($Name, $Spec, $Ver);
15257}
15258
15259sub cut_f_attrs($)
15260{
15261 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15262 return $2;
15263 }
15264 return "";
15265}
15266
15267sub highLight_Signature_PPos_Italic($$$$$)
15268{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015269 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15270 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15272 my $Return = "";
15273 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15274 $Return = $2;
15275 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015276 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015277 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015278 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015279 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015280 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015281 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015283 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 }
15285 return $Signature;
15286 }
15287 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15288 $Begin.=" " if($Begin!~/ \Z/);
15289 $End = cut_f_attrs($Signature);
15290 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015291 my ($Short, $Params) = split_Signature($Signature);
15292 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015293 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015294 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015295 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 $Part=~s/\A\s+|\s+\Z//g;
15297 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15298 if($Part=~/\([\*]+(\w+)\)/i) {
15299 $ParamName = $1;#func-ptr
15300 }
15301 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15302 $ParamName = $1;
15303 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015304 if(not $ParamName)
15305 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 push(@Parts, $Part_Styled);
15307 next;
15308 }
15309 if($ItalicParams and not $TName_Tid{1}{$Part}
15310 and not $TName_Tid{2}{$Part})
15311 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015312 my $Style = "<i>$ParamName</i>";
15313
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015314 if($Param_Pos ne ""
15315 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015316 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015317 }
15318 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015319 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015320 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015321
15322 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015323 }
15324 $Part_Styled=~s/,(\w)/, $1/g;
15325 push(@Parts, $Part_Styled);
15326 }
15327 if(@Parts)
15328 {
15329 foreach my $Num (0 .. $#Parts)
15330 {
15331 if($Num==$#Parts)
15332 { # add ")" to the last parameter
15333 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15334 }
15335 elsif(length($Parts[$Num])<=45) {
15336 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15337 }
15338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015339 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340 }
15341 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015342 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015343 }
15344 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015345 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015347 $Signature=~s!\[\]![&#160;]!g;
15348 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015349 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15350 if($SymbolVersion) {
15351 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15352 }
15353 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015354}
15355
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015356sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015357{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015358 my $Signature = $_[0];
15359 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15360 {
15361 $Signature=~s/\A\Q$ShortName\E\(//g;
15362 cut_f_attrs($Signature);
15363 $Signature=~s/\)\Z//;
15364 return ($ShortName, $Signature);
15365 }
15366
15367 # error
15368 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015369}
15370
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015371sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015373 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015374 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015375 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15376 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015377 foreach my $Pos (0 .. length($Params) - 1)
15378 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015379 my $S = substr($Params, $Pos, 1);
15380 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015381 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015382 }
15383 if($S eq "," and
15384 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015385 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015386 if($Comma)
15387 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015388 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015389 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015390 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391 }
15392 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015393 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394 }
15395 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015396 if(not $Sp)
15397 { # remove spaces
15398 foreach (@Parts)
15399 {
15400 s/\A //g;
15401 s/ \Z//g;
15402 }
15403 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015404 return @Parts;
15405}
15406
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015407sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408{
15409 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015410 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015411 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015412 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15413 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015414 $Center+=length($1);
15415 }
15416 foreach my $Pos (0 .. length($Sign)-1)
15417 {
15418 my $S = substr($Sign, $Pos, 1);
15419 if($S eq $Target)
15420 {
15421 if($B{"("}==$B{")"}
15422 and $B{"<"}==$B{">"}) {
15423 return $Center;
15424 }
15425 }
15426 if(defined $B{$S}) {
15427 $B{$S}+=1;
15428 }
15429 $Center+=1;
15430 }
15431 return 0;
15432}
15433
15434sub appendFile($$)
15435{
15436 my ($Path, $Content) = @_;
15437 return if(not $Path);
15438 if(my $Dir = get_dirname($Path)) {
15439 mkpath($Dir);
15440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015441 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015442 print FILE $Content;
15443 close(FILE);
15444}
15445
15446sub writeFile($$)
15447{
15448 my ($Path, $Content) = @_;
15449 return if(not $Path);
15450 if(my $Dir = get_dirname($Path)) {
15451 mkpath($Dir);
15452 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015453 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015454 print FILE $Content;
15455 close(FILE);
15456}
15457
15458sub readFile($)
15459{
15460 my $Path = $_[0];
15461 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015462 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015463 local $/ = undef;
15464 my $Content = <FILE>;
15465 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015466 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015467 $Content=~s/\r/\n/g;
15468 }
15469 return $Content;
15470}
15471
15472sub get_filename($)
15473{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015474 if(defined $Cache{"get_filename"}{$_[0]}) {
15475 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015477 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15478 return ($Cache{"get_filename"}{$_[0]}=$1);
15479 }
15480 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481}
15482
15483sub get_dirname($)
15484{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015485 if(defined $Cache{"get_dirname"}{$_[0]}) {
15486 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015487 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015488 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15489 return ($Cache{"get_dirname"}{$_[0]}=$1);
15490 }
15491 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015492}
15493
15494sub separate_path($) {
15495 return (get_dirname($_[0]), get_filename($_[0]));
15496}
15497
15498sub esc($)
15499{
15500 my $Str = $_[0];
15501 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15502 return $Str;
15503}
15504
15505sub readLineNum($$)
15506{
15507 my ($Path, $Num) = @_;
15508 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015509 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510 foreach (1 ... $Num) {
15511 <FILE>;
15512 }
15513 my $Line = <FILE>;
15514 close(FILE);
15515 return $Line;
15516}
15517
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015518sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015519{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015520 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015521 return () if(not $Path or not -f $Path);
15522 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015523 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15524 {
15525 foreach my $AttrVal (split(/;/, $1))
15526 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015527 if($AttrVal=~/(.+):(.+)/)
15528 {
15529 my ($Name, $Value) = ($1, $2);
15530 $Attributes{$Name} = $Value;
15531 }
15532 }
15533 }
15534 return \%Attributes;
15535}
15536
15537sub is_abs($) {
15538 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15539}
15540
15541sub get_abs_path($)
15542{ # abs_path() should NOT be called for absolute inputs
15543 # because it can change them
15544 my $Path = $_[0];
15545 if(not is_abs($Path)) {
15546 $Path = abs_path($Path);
15547 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015548 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015549}
15550
15551sub get_OSgroup()
15552{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015553 my $N = $Config{"osname"};
15554 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015555 return "macos";
15556 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015557 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015558 return "bsd";
15559 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015560 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 return "beos";
15562 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015563 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015564 return "symbian";
15565 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015566 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015567 return "windows";
15568 }
15569 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015570 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015571 }
15572}
15573
15574sub getGccVersion($)
15575{
15576 my $LibVersion = $_[0];
15577 if($GCC_VERSION{$LibVersion})
15578 { # dump version
15579 return $GCC_VERSION{$LibVersion};
15580 }
15581 elsif($UsedDump{$LibVersion}{"V"})
15582 { # old-version dumps
15583 return "unknown";
15584 }
15585 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15586 if(not $GccVersion) {
15587 return "unknown";
15588 }
15589 return $GccVersion;
15590}
15591
15592sub showArch($)
15593{
15594 my $Arch = $_[0];
15595 if($Arch eq "arm"
15596 or $Arch eq "mips") {
15597 return uc($Arch);
15598 }
15599 return $Arch;
15600}
15601
15602sub getArch($)
15603{
15604 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015605
15606 if($TargetArch) {
15607 return $TargetArch;
15608 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015609 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015610 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015611 return $CPU_ARCH{$LibVersion};
15612 }
15613 elsif($UsedDump{$LibVersion}{"V"})
15614 { # old-version dumps
15615 return "unknown";
15616 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015617
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015618 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619}
15620
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015621sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015622{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015623 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015625 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015626 if(getArch(1) ne getArch(2)
15627 or getArch(1) eq "unknown"
15628 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015629 { # don't show architecture in the header
15630 $ArchInfo="";
15631 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015632 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015633 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015634 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015635 }
15636 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015637 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015638 }
15639 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015640 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015641 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015642
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015643 my $V1 = $Descriptor{1}{"Version"};
15644 my $V2 = $Descriptor{2}{"Version"};
15645
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015646 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15647 {
15648 my $M1 = $UsedDump{1}{"M"};
15649 my $M2 = $UsedDump{2}{"M"};
15650
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015651 my $M1S = $M1;
15652 my $M2S = $M2;
15653
15654 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15655 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15656
15657 if($M1S eq $M2S
15658 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015659 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015660 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15661 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015662 }
15663 else
15664 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015665 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15666 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015667 }
15668 }
15669 else
15670 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015671 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015672 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015673 }
15674
15675 $Title .= $ArchInfo;
15676
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015677 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015678 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015679 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015680 $Title = "<h1>".$Title."</h1>\n";
15681 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015682}
15683
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015684sub get_CheckedHeaders($)
15685{
15686 my $LibVersion = $_[0];
15687
15688 my @Headers = ();
15689
15690 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15691 {
15692 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015693
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015694 if(not is_target_header($File, $LibVersion)) {
15695 next;
15696 }
15697
15698 if(skipHeader($File, $LibVersion)) {
15699 next;
15700 }
15701
15702 push(@Headers, $Path);
15703 }
15704
15705 return @Headers;
15706}
15707
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015708sub get_SourceInfo()
15709{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015710 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015711
15712 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015713 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015714 $CheckedHeaders = "<a name='Headers'></a>";
15715 if($OldStyle) {
15716 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15717 }
15718 else {
15719 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15720 }
15721 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015722 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 +040015723 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015724 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15725 my $Name = get_filename($Identity);
15726 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15727 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015728 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015729 $CheckedHeaders .= "</div>\n";
15730 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015731 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015732
15733 if(my @Sources = keys(%{$Registered_Sources{1}}))
15734 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015735 $CheckedSources = "<a name='Sources'></a>";
15736 if($OldStyle) {
15737 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15738 }
15739 else {
15740 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15741 }
15742 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015743 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15744 {
15745 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15746 my $Name = get_filename($Identity);
15747 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15748 $CheckedSources .= $Name.$Comment."<br/>\n";
15749 }
15750 $CheckedSources .= "</div>\n";
15751 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15752 }
15753
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015754 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015755 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015756 $CheckedLibs = "<a name='Libs'></a>";
15757 if($OldStyle) {
15758 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15759 }
15760 else {
15761 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15762 }
15763 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15764 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015765 $CheckedLibs .= $Library."<br/>\n";
15766 }
15767 $CheckedLibs .= "</div>\n";
15768 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015770
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015771 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15772}
15773
15774sub get_ObjTitle()
15775{
15776 if(defined $UsedDump{1}{"DWARF"}) {
15777 return "Objects";
15778 }
15779 else {
15780 return ucfirst($SLIB_TYPE)." Libraries";
15781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782}
15783
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015784sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015786 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015788
15789 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015790 {
15791 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015792 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015793 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015794 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015795 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015796 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015797 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015798
15799 if($Severity ne $TargetSeverity) {
15800 next;
15801 }
15802
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015803 if($Kinds_Target{$Kind}{$Target}) {
15804 next;
15805 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015806
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 $Kinds_Target{$Kind}{$Target} = 1;
15808 $Type_Problems_Count += 1;
15809 }
15810 }
15811 }
15812 return $Type_Problems_Count;
15813}
15814
15815sub get_Summary($)
15816{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015817 my $Level = $_[0];
15818 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015819 $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 +040015820 %{$RESULT{$Level}} = (
15821 "Problems"=>0,
15822 "Warnings"=>0,
15823 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015824 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015825 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015827 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015828 {
15829 if(not defined $CompatRules{$Level}{$Kind})
15830 { # unknown rule
15831 if(not $UnknownRules{$Level}{$Kind})
15832 { # only one warning
15833 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15834 $UnknownRules{$Level}{$Kind}=1;
15835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015836 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015837 }
15838 }
15839 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015840 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15841 {
15842 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15843 {
15844 if(not defined $CompatRules{$Level}{$Kind})
15845 { # unknown rule
15846 if(not $UnknownRules{$Level}{$Kind})
15847 { # only one warning
15848 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15849 $UnknownRules{$Level}{$Kind}=1;
15850 }
15851 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15852 }
15853 }
15854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015855 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015856 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015857 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015858 {
15859 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15860 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015863 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015864 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015865 $Added += 1;
15866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015867 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015868 {
15869 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015870 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015871 }
15872 else
15873 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015874 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875 $I_Other += 1;
15876 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015877 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015878 $I_Problems_High += 1;
15879 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015880 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015881 $I_Problems_Medium += 1;
15882 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015883 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015884 $I_Problems_Low += 1;
15885 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015886 if(($Severity ne "Low" or $StrictCompat)
15887 and $Severity ne "Safe") {
15888 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015889 }
15890 }
15891 }
15892 }
15893 }
15894 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015895
15896 my %MethodTypeIndex = ();
15897
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015898 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015899 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015900 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15901 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015902 {
15903 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15904 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015905 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15906 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015907 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15909 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015910
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015911 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15912 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015913 next;
15914 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015915 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15916 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15917
15918 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015919
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015920 if(($Severity ne "Low" or $StrictCompat)
15921 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015922 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015923 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015924 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015925 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015926 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015927 }
15928 }
15929 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015930 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 }
15934 }
15935 }
15936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015937
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015938 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15939 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15940 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15941 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015942
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015943 # changed and removed public symbols
15944 my $SCount = keys(%{$CheckedSymbols{$Level}});
15945 if($ExtendedCheck)
15946 { # don't count external_func_0 for constants
15947 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015948 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015949 if($SCount)
15950 {
15951 my %Weight = (
15952 "High" => 100,
15953 "Medium" => 50,
15954 "Low" => 25
15955 );
15956 foreach (keys(%{$TotalAffected{$Level}})) {
15957 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015958 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015959 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015960 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015961 else {
15962 $RESULT{$Level}{"Affected"} = 0;
15963 }
15964
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015965 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15966 if($RESULT{$Level}{"Affected"}>=100) {
15967 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015968 }
15969
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015970 $RESULT{$Level}{"Problems"} += $Removed;
15971 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015972 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015973 if($StrictCompat) {
15974 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15975 }
15976 else {
15977 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015980 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015982 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015983 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015984 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015985 if($Severity eq "Safe")
15986 {
15987 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015988 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015989 elsif($Severity eq "Low")
15990 {
15991 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015992 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015993 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015994 }
15995
15996 if($C_Problems_Low)
15997 {
15998 if($StrictCompat) {
15999 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
16000 }
16001 else {
16002 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016003 }
16004 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016005 if($RESULT{$Level}{"Problems"}
16006 and $RESULT{$Level}{"Affected"}) {
16007 $RESULT{$Level}{"Verdict"} = "incompatible";
16008 }
16009 else {
16010 $RESULT{$Level}{"Verdict"} = "compatible";
16011 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016012
16013 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
16014 if(not $TotalTypes)
16015 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016016 $TotalTypes = keys(%{$TName_Tid{1}});
16017 }
16018
16019 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
16020 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016021 my ($ClangV1, $ClangV2) = ($CLANG_VERSION{1}, $CLANG_VERSION{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022
16023 my ($TestInfo, $TestResults, $Problem_Summary) = ();
16024
16025 if($ReportFormat eq "xml")
16026 { # XML
16027 # test info
16028 $TestInfo .= " <library>$TargetLibraryName</library>\n";
16029 $TestInfo .= " <version1>\n";
16030 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016031 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016032 if($GccV1) {
16033 $TestInfo .= " <gcc>$GccV1</gcc>\n";
16034 }
16035 elsif($ClangV1) {
16036 $TestInfo .= " <clang>$ClangV1</clang>\n";
16037 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016038 $TestInfo .= " </version1>\n";
16039
16040 $TestInfo .= " <version2>\n";
16041 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016042 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016043 if($GccV2) {
16044 $TestInfo .= " <gcc>$GccV2</gcc>\n";
16045 }
16046 elsif($ClangV2) {
16047 $TestInfo .= " <clang>$ClangV2</clang>\n";
16048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 $TestInfo .= " </version2>\n";
16050 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
16051
16052 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016053 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016054 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016055 $TestResults .= " <headers>\n";
16056 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
16057 {
16058 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
16059 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16060 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16061 }
16062 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016064
16065 if(my @Sources = keys(%{$Registered_Sources{1}}))
16066 {
16067 $TestResults .= " <sources>\n";
16068 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16069 {
16070 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16071 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16072 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16073 }
16074 $TestResults .= " </sources>\n";
16075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016076
16077 $TestResults .= " <libs>\n";
16078 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16079 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016080 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016081 $TestResults .= " <name>$Library</name>\n";
16082 }
16083 $TestResults .= " </libs>\n";
16084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016085 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086 $TestResults .= " <types>".$TotalTypes."</types>\n";
16087
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016088 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16089 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016090 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16091
16092 # problem summary
16093 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16094 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16095
16096 $Problem_Summary .= " <problems_with_types>\n";
16097 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16098 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16099 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16100 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16101 $Problem_Summary .= " </problems_with_types>\n";
16102
16103 $Problem_Summary .= " <problems_with_symbols>\n";
16104 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16105 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16106 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016107 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108 $Problem_Summary .= " </problems_with_symbols>\n";
16109
16110 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016111 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016112 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016114 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16115
16116 return ($TestInfo.$TestResults.$Problem_Summary, "");
16117 }
16118 else
16119 { # HTML
16120 # test info
16121 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016122 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016123
16124 if($TargetComponent eq "library") {
16125 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16126 }
16127 else {
16128 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016130
16131 my (@VInf1, @VInf2, $AddTestInfo) = ();
16132 if($Arch1 ne "unknown"
16133 and $Arch2 ne "unknown")
16134 { # CPU arch
16135 if($Arch1 eq $Arch2)
16136 { # go to the separate section
Andrey Ponomarenko19b61de2016-08-31 19:45:06 +030016137 $AddTestInfo .= "<tr><th>Arch</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016138 }
16139 else
16140 { # go to the version number
16141 push(@VInf1, showArch($Arch1));
16142 push(@VInf2, showArch($Arch2));
16143 }
16144 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016145 if($Level eq "Binary"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146 and $OStarget ne "windows")
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016147 {
16148 if($GccV1 ne "unknown"
16149 and $GccV2 ne "unknown")
16150 { # GCC version
16151 if($GccV1 eq $GccV2)
16152 { # go to the separate section
16153 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16154 }
16155 else
16156 { # go to the version number
16157 push(@VInf1, "gcc ".$GccV1);
16158 push(@VInf2, "gcc ".$GccV2);
16159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016161 elsif($ClangV1
16162 and $ClangV2)
16163 { # Clang version
16164 if($ClangV1 eq $ClangV2)
16165 { # go to the separate section
16166 $AddTestInfo .= "<tr><th>Clang Version</th><td>$ClangV1</td></tr>\n";
16167 }
16168 else
16169 { # go to the version number
16170 push(@VInf1, "clang ".$ClangV1);
16171 push(@VInf2, "clang ".$ClangV2);
16172 }
16173 }
16174 elsif($GccV1 ne "unknown" and $ClangV2)
16175 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176 push(@VInf1, "gcc ".$GccV1);
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016177 push(@VInf2, "clang ".$ClangV2);
16178 }
16179 elsif($ClangV1 and $GccV2 ne "unknown")
16180 {
16181 push(@VInf1, "clang ".$ClangV1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016182 push(@VInf2, "gcc ".$GccV2);
16183 }
16184 }
16185 # show long version names with GCC version and CPU architecture name (if different)
16186 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16187 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16188 $TestInfo .= $AddTestInfo;
16189 #if($COMMON_LANGUAGE{1}) {
16190 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16191 #}
16192 if($ExtendedCheck) {
16193 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016195 if($JoinReport)
16196 {
16197 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016198 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016199 }
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030016200 elsif($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016201 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016202 }
16203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204 $TestInfo .= "</table>\n";
16205
16206 # test results
16207 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016208 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016209
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016210 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016211 {
16212 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16213 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16214 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016215
16216 if(my @Sources = keys(%{$Registered_Sources{1}}))
16217 {
16218 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16219 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016221
16222 if(not $ExtendedCheck)
16223 {
16224 my $Libs_Link = "0";
16225 $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 +040016226 $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 +040016227 }
16228
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016229 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016231 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016232 if($JoinReport) {
16233 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16234 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016235
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016236 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016237
16238 $TestResults .= "<tr><th>Compatibility</th>\n";
16239 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16240 {
16241 my $Cl = "incompatible";
16242 if($BC_Rate>=90) {
16243 $Cl = "warning";
16244 }
16245 elsif($BC_Rate>=80) {
16246 $Cl = "almost_compatible";
16247 }
16248
16249 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016250 }
16251 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016252 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016253 }
16254 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 $TestResults .= "</table>\n";
16256
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016257 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258 # problem summary
16259 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16262
16263 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016264 if($Added>0)
16265 {
16266 if($JoinReport) {
16267 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16268 }
16269 else {
16270 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16271 }
16272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016274 $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 +040016275
16276 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016277 if($Removed>0)
16278 {
16279 if($JoinReport) {
16280 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16281 }
16282 else {
16283 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16284 }
16285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016287 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016288 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289
16290 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 $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 +040016292 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016293 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016294 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016295
16296 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016297 $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 +040016298 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016299 $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 +040016300
16301 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016302 $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 +040016303 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016304 $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 +040016305
16306 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016307 $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 +040016308 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016309 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016310 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311
16312 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016313 $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 +040016314 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016315 $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 +040016316
16317 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016318 $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 +040016319 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016320 $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 +040016321
16322 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016323 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16324 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016325 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016326 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016327 $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 +040016328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016330 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016331 {
16332 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016333 $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 +030016334 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016335 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016336
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016337 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016338 {
16339 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016340 $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 +030016341 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016344 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016345 {
16346 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016347 $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 +030016348 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016349 }
16350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 $META_DATA .= "tool_version:$TOOL_VERSION";
16352 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016354 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16355 }
16356}
16357
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016358sub getStyle($$$)
16359{
16360 my ($Subj, $Act, $Num) = @_;
16361 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016362 "Added"=>"new",
16363 "Removed"=>"failed",
16364 "Safe"=>"passed",
16365 "Low"=>"warning",
16366 "Medium"=>"failed",
16367 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016368 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016369
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016370 if($Num>0) {
16371 return " class='".$Style{$Act}."'";
16372 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016373
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016374 return "";
16375}
16376
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377sub show_number($)
16378{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016379 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016381 my $Num = cut_off_number($_[0], 2, 0);
16382 if($Num eq "0")
16383 {
16384 foreach my $P (3 .. 7)
16385 {
16386 $Num = cut_off_number($_[0], $P, 1);
16387 if($Num ne "0") {
16388 last;
16389 }
16390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016391 }
16392 if($Num eq "0") {
16393 $Num = $_[0];
16394 }
16395 return $Num;
16396 }
16397 return $_[0];
16398}
16399
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016400sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016401{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016403 if($num!~/\./)
16404 {
16405 $num .= ".";
16406 foreach (1 .. $digs_to_cut-1) {
16407 $num .= "0";
16408 }
16409 }
16410 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16411 {
16412 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16413 $num .= "0";
16414 }
16415 }
16416 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16417 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16418 }
16419 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 if($z) {
16421 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 return $num;
16424}
16425
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016426sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016427{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016428 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016429 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016430
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016431 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016432 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16433 {
16434 my $Header = $Constants{1}{$Constant}{"Header"};
16435 if(not $Header)
16436 { # added
16437 $Header = $Constants{2}{$Constant}{"Header"}
16438 }
16439
16440 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16441 {
16442 if(not defined $CompatRules{$Level}{$Kind}) {
16443 next;
16444 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016445 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016446 next;
16447 }
16448 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016450 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016452 if($ReportFormat eq "xml")
16453 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016454 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
16456 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016457 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 {
16459 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016460 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16461 {
16462 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16463 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16464 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016465
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016466 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16467 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16468 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016469 if($Overcome) {
16470 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16471 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016472 $CHANGED_CONSTANTS .= " </problem>\n";
16473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016474 $CHANGED_CONSTANTS .= " </constant>\n";
16475 }
16476 $CHANGED_CONSTANTS .= " </header>\n";
16477 }
16478 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16479 }
16480 else
16481 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016482 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016483 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 {
16485 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016486 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016488 my $Report = "";
16489
16490 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16491 {
16492 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16493 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016494 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016495 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016496 }
16497 if($Report)
16498 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016499 $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 +030016500 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016501 $Report = insertIDs($Report);
16502 }
16503 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
16505 $CHANGED_CONSTANTS .= "<br/>\n";
16506 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 if($CHANGED_CONSTANTS)
16508 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016509 my $Title = "Problems with Constants, $TargetSeverity Severity";
16510 if($TargetSeverity eq "Safe")
16511 { # Safe Changes
16512 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016513 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016514 if($OldStyle) {
16515 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16516 }
16517 else {
16518 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16519 }
16520 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016521 }
16522 }
16523 return $CHANGED_CONSTANTS;
16524}
16525
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526sub getTitle($$$)
16527{
16528 my ($Header, $Library, $NameSpace) = @_;
16529 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016530
16531 # if($Library and $Library!~/\.\w+\Z/) {
16532 # $Library .= " (.$LIB_EXT)";
16533 # }
16534
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016535 if($Header and $Library)
16536 {
16537 $Title .= "<span class='h_name'>$Header</span>";
16538 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16539 }
16540 elsif($Library) {
16541 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16542 }
16543 elsif($Header) {
16544 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16545 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016547 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016548 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016550
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016551 return $Title;
16552}
16553
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554sub get_Report_Added($)
16555{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016557 my $ADDED_INTERFACES = "";
16558 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 {
16565 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16566 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016567 if($Level eq "Source" and $ReportFormat eq "html")
16568 { # do not show library name in HTML report
16569 $DyLib = "";
16570 }
16571 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 }
16573 }
16574 }
16575 if($ReportFormat eq "xml")
16576 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 {
16579 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 {
16582 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016583 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16585 }
16586 $ADDED_INTERFACES .= " </library>\n";
16587 }
16588 $ADDED_INTERFACES .= " </header>\n";
16589 }
16590 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16591 }
16592 else
16593 { # HTML
16594 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016595 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016599 my %NameSpaceSymbols = ();
16600 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016601 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016602 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016603 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016605 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16606 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016607 foreach my $Interface (@SortedInterfaces)
16608 {
16609 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 my $Signature = get_Signature($Interface, 2);
16611 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016612 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016613 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016614 if($Interface=~/\A(_Z|\?)/)
16615 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016616 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016617 $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 +040016618 }
16619 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016620 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016621 }
16622 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016623 else
16624 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016626 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 }
16628 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016629 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 }
16631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016633 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 }
16636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016637 if($ADDED_INTERFACES)
16638 {
16639 my $Anchor = "<a name='Added'></a>";
16640 if($JoinReport) {
16641 $Anchor = "<a name='".$Level."_Added'></a>";
16642 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016643 if($OldStyle) {
16644 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16645 }
16646 else {
16647 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16648 }
16649 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 }
16651 }
16652 return $ADDED_INTERFACES;
16653}
16654
16655sub get_Report_Removed($)
16656{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016657 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016658 my $REMOVED_INTERFACES = "";
16659 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016660 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016662 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016663 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016664 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016666 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16667 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016668 if($Level eq "Source" and $ReportFormat eq "html")
16669 { # do not show library name in HTML report
16670 $DyLib = "";
16671 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016672 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 }
16674 }
16675 }
16676 if($ReportFormat eq "xml")
16677 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016678 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 {
16680 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 {
16683 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016684 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16685 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016686 }
16687 $REMOVED_INTERFACES .= " </library>\n";
16688 }
16689 $REMOVED_INTERFACES .= " </header>\n";
16690 }
16691 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16692 }
16693 else
16694 { # HTML
16695 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016696 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016697 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016698 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 my %NameSpaceSymbols = ();
16701 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016702 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016703 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016704 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016706 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16707 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016708 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016709 {
16710 $Removed_Number += 1;
16711 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016712 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016714 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016715 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016716 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016717 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016718 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016719 $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 +040016720 }
16721 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016722 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 }
16724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 else
16726 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 }
16730 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016731 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016732 }
16733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 }
16735 }
16736 $REMOVED_INTERFACES .= "<br/>\n";
16737 }
16738 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016739 if($REMOVED_INTERFACES)
16740 {
16741 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16742 if($JoinReport) {
16743 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16744 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016745 if($OldStyle) {
16746 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16747 }
16748 else {
16749 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16750 }
16751
16752 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 }
16754 }
16755 return $REMOVED_INTERFACES;
16756}
16757
16758sub getXmlParams($$)
16759{
16760 my ($Content, $Problem) = @_;
16761 return "" if(not $Content or not $Problem);
16762 my %XMLparams = ();
16763 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16764 {
16765 my $Macro = "\@".lc($Attr);
16766 if($Content=~/\Q$Macro\E/) {
16767 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16768 }
16769 }
16770 my @PString = ();
16771 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016772 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016773 }
16774 if(@PString) {
16775 return " ".join(" ", @PString);
16776 }
16777 else {
16778 return "";
16779 }
16780}
16781
16782sub addMarkup($)
16783{
16784 my $Content = $_[0];
16785 # auto-markup
16786 $Content=~s/\n[ ]*//; # spaces
16787 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16788 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016789 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016790 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16791 if($Content=~/\ANOTE:/)
16792 { # notes
16793 $Content=~s!(NOTE):!<b>$1</b>:!g;
16794 }
16795 else {
16796 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16797 }
16798 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16799 my @Keywords = (
16800 "void",
16801 "const",
16802 "static",
16803 "restrict",
16804 "volatile",
16805 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016806 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 );
16808 my $MKeys = join("|", @Keywords);
16809 foreach (@Keywords) {
16810 $MKeys .= "|non-".$_;
16811 }
16812 $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 +040016813
16814 # Markdown
16815 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16816 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817 return $Content;
16818}
16819
16820sub applyMacroses($$$$)
16821{
16822 my ($Level, $Kind, $Content, $Problem) = @_;
16823 return "" if(not $Content or not $Problem);
16824 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16825 $Content = addMarkup($Content);
16826 # macros
16827 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16828 {
16829 my $Macro = "\@".lc($Attr);
16830 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016831 if(not defined $Value
16832 or $Value eq "") {
16833 next;
16834 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016835
16836 if(index($Content, $Macro)==-1) {
16837 next;
16838 }
16839
16840 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16841 and $Kind!~/_Type_/
16842 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016843 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016844 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016845 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 $Value = black_name($Value);
16847 }
16848 elsif($Value=~/\s/) {
16849 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16850 }
16851 elsif($Value=~/\A\d+\Z/
16852 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16853 { # bits to bytes
16854 if($Value % $BYTE_SIZE)
16855 { # bits
16856 if($Value==1) {
16857 $Value = "<b>".$Value."</b> bit";
16858 }
16859 else {
16860 $Value = "<b>".$Value."</b> bits";
16861 }
16862 }
16863 else
16864 { # bytes
16865 $Value /= $BYTE_SIZE;
16866 if($Value==1) {
16867 $Value = "<b>".$Value."</b> byte";
16868 }
16869 else {
16870 $Value = "<b>".$Value."</b> bytes";
16871 }
16872 }
16873 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016874 else
16875 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016876 $Value = "<b>".htmlSpecChars($Value)."</b>";
16877 }
16878 $Content=~s/\Q$Macro\E/$Value/g;
16879 }
16880
16881 if($Content=~/(\A|[^\@\w])\@\w/)
16882 {
16883 if(not $IncompleteRules{$Level}{$Kind})
16884 { # only one warning
16885 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16886 $IncompleteRules{$Level}{$Kind} = 1;
16887 }
16888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 return $Content;
16890}
16891
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016892sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016893{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016894 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016895 my $INTERFACE_PROBLEMS = "";
16896 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016897
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016900 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16901 if($SV and defined $CompatProblems{$Level}{$SN}) {
16902 next;
16903 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016904 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16905 my $DyLib = $Symbol_Library{1}{$Symbol};
16906 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16907 { # Symbol with Version
16908 $DyLib = $Symbol_Library{1}{$VSym};
16909 }
16910 if(not $DyLib)
16911 { # const global data
16912 $DyLib = "";
16913 }
16914 if($Level eq "Source" and $ReportFormat eq "html")
16915 { # do not show library name in HTML report
16916 $DyLib = "";
16917 }
16918
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016919 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 {
16921 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016922 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016923 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016924 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16925 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016927 if($Severity eq $TargetSeverity)
16928 {
16929 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16930 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 }
16932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016933 }
16934 }
16935 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 if($ReportFormat eq "xml")
16938 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016939 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 {
16941 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016942 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943 {
16944 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016945 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16946 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 {
16948 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016949 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 {
16951 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16952 {
16953 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016954 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016955
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16957 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16958 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16959 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16960 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016961 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16962 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 $INTERFACE_PROBLEMS .= " </problem>\n";
16965 }
16966 }
16967 $INTERFACE_PROBLEMS .= " </symbol>\n";
16968 }
16969 $INTERFACE_PROBLEMS .= " </library>\n";
16970 }
16971 $INTERFACE_PROBLEMS .= " </header>\n";
16972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016973 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 }
16975 else
16976 { # HTML
16977 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016978 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 my (%NameSpaceSymbols, %NewSignature) = ();
16983 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016984 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016988 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016989 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 +040016990 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016992 my $Signature = get_Signature($Symbol, 1);
16993 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016995 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016996 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016997 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016998 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016999 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017000 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017001 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017002 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017003 }
17004 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17005 {
17006 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017007 $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 +040017008 $ProblemNum += 1;
17009 $ProblemsNum += 1;
17010 }
17011 }
17012 }
17013 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017014 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017015 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017016 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017018 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017019 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017020
17021 if($NameSpace)
17022 {
17023 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
17024 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017026
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017027 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
17028 if($OldStyle) {
17029 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
17030 }
17031 else {
17032 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17033 }
17034 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017035 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017036
17037 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017038 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017039 if($NameSpace) {
17040 $NSign = cut_Namespace($NSign, $NameSpace);
17041 }
17042 $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 +040017043 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017044
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017045 if($Symbol=~/\A(_Z|\?)/) {
17046 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
17047 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017048
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017049 $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 +040017050 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017051 }
17052 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017053 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017054 }
17055 }
17056 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017058 if($INTERFACE_PROBLEMS)
17059 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017060 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
17061 my $Title = "Problems with Symbols, $TargetSeverity Severity";
17062 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017063 { # Safe Changes
17064 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017066 if($OldStyle) {
17067 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
17068 }
17069 else {
17070 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
17071 }
17072 $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 +040017073 }
17074 }
17075 return $INTERFACE_PROBLEMS;
17076}
17077
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017078sub cut_Namespace($$)
17079{
17080 my ($N, $Ns) = @_;
17081 $N=~s/\b\Q$Ns\E:://g;
17082 return $N;
17083}
17084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017085sub get_Report_TypeProblems($$)
17086{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017087 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017088 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017089
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017090 my %ReportMap = ();
17091 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017092
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017093 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017095 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17096
17097 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017098 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017099 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017100 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017101 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017102 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017103
17104 if($Severity eq $TargetSeverity)
17105 {
17106 $ReportMap{$HeaderName}{$TypeName} = 1;
17107 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017112
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017113 if($ReportFormat eq "xml")
17114 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017115 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017116 {
17117 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017118 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017120 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017121 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017122 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017124 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017126 $Kinds_Locations{$Kind}{$Location} = 1;
17127
17128 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17129 if($Kinds_Target{$Kind}{$Target}) {
17130 next;
17131 }
17132 $Kinds_Target{$Kind}{$Target} = 1;
17133
17134 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17136 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17137 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17138 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17139 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017140 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17141 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 $TYPE_PROBLEMS .= " </problem>\n";
17144 }
17145 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017146 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17147 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 $TYPE_PROBLEMS .= showVTables($TypeName);
17149 }
17150 $TYPE_PROBLEMS .= " </type>\n";
17151 }
17152 $TYPE_PROBLEMS .= " </header>\n";
17153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017154 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 }
17156 else
17157 { # HTML
17158 my $ProblemsNum = 0;
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 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017161 my (%NameSpace_Type) = ();
17162 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017163 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017164 }
17165 foreach my $NameSpace (sort keys(%NameSpace_Type))
17166 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017167 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017168 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 +040017169 foreach my $TypeName (@SortedTypes)
17170 {
17171 my $ProblemNum = 1;
17172 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017173 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017174
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017175 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017177 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017179 $Kinds_Locations{$Kind}{$Location} = 1;
17180
17181 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17182 if($Kinds_Target{$Kind}{$Target}) {
17183 next;
17184 }
17185 $Kinds_Target{$Kind}{$Target} = 1;
17186
17187 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017188 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17189 {
17190 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017191 $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 +040017192 $ProblemNum += 1;
17193 $ProblemsNum += 1;
17194 }
17195 }
17196 }
17197 $ProblemNum -= 1;
17198 if($TYPE_REPORT)
17199 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017200 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017202 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017203 $ShowVTables = showVTables($TypeName);
17204 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017205
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017206 my $ShowType = show_Type($TypeName, 1, 1);
17207
17208 if($NameSpace)
17209 {
17210 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17211 $ShowType = cut_Namespace($ShowType, $NameSpace);
17212 $Affected = cut_Namespace($Affected, $NameSpace);
17213 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17214 }
17215
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017216 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17217 if($OldStyle) {
17218 $TYPE_PROBLEMS .= " ($ProblemNum)";
17219 }
17220 else {
17221 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17222 }
17223 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017224 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17225 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17226 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17227 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228 }
17229 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017230 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017231 }
17232 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 if($TYPE_PROBLEMS)
17235 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017236 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17237 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017238 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239 { # Safe Changes
17240 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017242 if($OldStyle) {
17243 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17244 }
17245 else {
17246 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17247 }
17248 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017249 }
17250 }
17251 return $TYPE_PROBLEMS;
17252}
17253
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017254sub show_Type($$$)
17255{
17256 my ($Name, $Html, $LibVersion) = @_;
17257 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17258 $TType = lc($TType);
17259 if($TType=~/struct|union|enum/) {
17260 $Name=~s/\A\Q$TType\E //g;
17261 }
17262 if($Html) {
17263 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17264 }
17265 else {
17266 $Name = $TType." ".$Name;
17267 }
17268 return $Name;
17269}
17270
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017271sub get_Anchor($$$)
17272{
17273 my ($Kind, $Level, $Severity) = @_;
17274 if($JoinReport)
17275 {
17276 if($Severity eq "Safe") {
17277 return "Other_".$Level."_Changes_In_".$Kind."s";
17278 }
17279 else {
17280 return $Kind."_".$Level."_Problems_".$Severity;
17281 }
17282 }
17283 else
17284 {
17285 if($Severity eq "Safe") {
17286 return "Other_Changes_In_".$Kind."s";
17287 }
17288 else {
17289 return $Kind."_Problems_".$Severity;
17290 }
17291 }
17292}
17293
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017294sub showVTables($)
17295{
17296 my $TypeName = $_[0];
17297 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017298 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017299 if(defined $Type1{"VTable"}
17300 and keys(%{$Type1{"VTable"}}))
17301 {
17302 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017303 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017304 if(defined $Type2{"VTable"}
17305 and keys(%{$Type2{"VTable"}}))
17306 {
17307 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17308 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017309 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017310 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017311 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17312 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017313 }
17314 my $VTABLES = "";
17315 if($ReportFormat eq "xml")
17316 { # XML
17317 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017318 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017319 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017320 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017321 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17322 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 $VTABLES .= " </entry>\n";
17324 }
17325 $VTABLES .= " </vtable>\n\n";
17326 }
17327 else
17328 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017329 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017330 $VTABLES .= "<tr><th>Offset</th>";
17331 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017333 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334 {
17335 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017336
17337 my $E1 = $Entries{$Index}{"E1"};
17338 my $E2 = $Entries{$Index}{"E2"};
17339
17340 if($E1 ne $E2
17341 and $E1!~/ 0x/
17342 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017343 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017344 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017345 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017346 $Color1 = " class='failed'";
17347 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017348 }
17349 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017350 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017351 }
17352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017353 $VTABLES .= "<tr><th>".$Index."</th>\n";
17354 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17355 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017356 }
17357 $VTABLES .= "</table><br/>\n";
17358 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017359 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 }
17361 return $VTABLES;
17362 }
17363 }
17364 return "";
17365}
17366
17367sub simpleVEntry($)
17368{
17369 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017370 if(not defined $VEntry
17371 or $VEntry eq "") {
17372 return "";
17373 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017374
17375 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017376 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17377 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17378 if($VEntry=~/\A_ZThn.+\Z/) {
17379 $VEntry = "non-virtual thunk";
17380 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017381 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017382 # support for old GCC versions
17383 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17384 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17385 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017386 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17387 return $VEntry;
17388}
17389
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017390sub adjustParamPos($$$)
17391{
17392 my ($Pos, $Symbol, $LibVersion) = @_;
17393 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17394 {
17395 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17396 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17397 {
17398 return $Pos-1;
17399 }
17400
17401 return $Pos;
17402 }
17403
17404 return undef;
17405}
17406
17407sub getParamPos($$$)
17408{
17409 my ($Name, $Symbol, $LibVersion) = @_;
17410
17411 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17412 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17413 {
17414 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17415 foreach (keys(%{$Info->{"Param"}}))
17416 {
17417 if($Info->{"Param"}{$_}{"name"} eq $Name)
17418 {
17419 return $_;
17420 }
17421 }
17422 }
17423
17424 return undef;
17425}
17426
17427sub getParamName($)
17428{
17429 my $Loc = $_[0];
17430 $Loc=~s/\->.*//g;
17431 return $Loc;
17432}
17433
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017434sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017436 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017437
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017438 my $LIMIT = 10;
17439 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017440 $LIMIT = $AffectLimit;
17441 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017442
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017443 my @Kinds = sort keys(%{$Kinds_Locations});
17444 my %KLocs = ();
17445 foreach my $Kind (@Kinds)
17446 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017447 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 +030017448 $KLocs{$Kind} = \@Locs;
17449 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017450
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017451 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017452 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017453 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017454 if(index($Symbol, "_Z")==0
17455 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 { # duplicated problems for C2 constructors, D2 and D0 destructors
17457 next;
17458 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017459
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017460 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017462 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017463 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017464 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 next;
17466 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017467
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017468 if(index($Symbol, "\@")!=-1
17469 or index($Symbol, "\$")!=-1)
17470 {
17471 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17472
17473 if($Level eq "Source")
17474 { # remove symbol version
17475 $Symbol = $SN;
17476 }
17477
17478 if($SV and defined $CompatProblems{$Level}{$SN}
17479 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17480 { # duplicated problems for versioned symbols
17481 next;
17482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017483 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017484
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017485 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017486 if($Type_Name ne $Target_TypeName) {
17487 next;
17488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017489
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017490 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017491 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017492 }
17493 }
17494 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017495
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017496 %KLocs = (); # clear
17497
17498 my %SymSel = ();
17499 my $Num = 0;
17500 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017501 {
17502 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17503 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017504 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017505 {
17506 $SymSel{$Symbol}{"Loc"} = $Loc;
17507 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017508 last LOOP;
17509 }
17510 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017511
17512 $Num += 1;
17513
17514 if($Num>=$LIMIT) {
17515 last;
17516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017517 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017519 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017521 if($ReportFormat eq "xml")
17522 { # XML
17523 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017524
17525 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017526 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017527 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017528 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017529
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017530 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017531 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017533 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017534 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017535 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017536 $Target .= " param=\"$PName\"";
17537 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017538 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017539 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017540 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017541 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017542 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017543 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017544 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017545
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017546 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017547 $Target .= " field=\"$1\"";
17548 }
17549
17550 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017551 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 $Affected .= " </symbol>\n";
17553 }
17554 $Affected .= " </affected>\n";
17555 }
17556 else
17557 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017558 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017559 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017560 my $Kind = $SymSel{$Symbol}{"Kind"};
17561 my $Loc = $SymSel{$Symbol}{"Loc"};
17562
17563 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017564 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017565 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017566 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17567
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017568 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017569 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017571
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017572 if(keys(%SymLocKind)>$LIMIT) {
17573 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017574 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017575
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017576 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017577 if($Affected)
17578 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017579 my $Num = keys(%SymLocKind);
17580 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017581 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017582 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017583 }
17584 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017586 return $Affected;
17587}
17588
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017589sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017590{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017591 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017592 if($L2=~/\A(retval|this)\b/
17593 and $L1!~/\A(retval|this)\b/)
17594 {
17595 if($L1!~/\-\>/) {
17596 return 1;
17597 }
17598 elsif($L2=~/\-\>/) {
17599 return 1;
17600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017601 }
17602 return 0;
17603}
17604
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017605sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017606{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017607 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017608
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017609 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017610
17611 my $Location_I = $Location;
17612 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017614 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017615
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017616 if($Kind eq "Overridden_Virtual_Method"
17617 or $Kind eq "Overridden_Virtual_Method_B") {
17618 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17619 }
17620 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17621 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017622 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17623
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017624 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17625 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017626 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17627 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17628
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017629 if($ClassName eq $Problem{"Type_Name"}) {
17630 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17631 }
17632 else {
17633 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17634 }
17635 }
17636 else
17637 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017638 my $TypeID = undef;
17639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017640 if($Location=~/retval/)
17641 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017642 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017643 push(@Sentence, "Field \'".$Location."\' in return value");
17644 }
17645 else {
17646 push(@Sentence, "Return value");
17647 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017648
17649 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017650 }
17651 elsif($Location=~/this/)
17652 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017653 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017654 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17655 }
17656 else {
17657 push(@Sentence, "\'this\' pointer");
17658 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017659
17660 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017661 }
17662 else
17663 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017664
17665 my $PName = getParamName($Location);
17666 my $PPos = getParamPos($PName, $Symbol, 1);
17667
17668 if(index($Location, "->")!=-1) {
17669 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017670 }
17671 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017672 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017673 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017674 if($PName) {
17675 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017676 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017677
17678 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17679 }
17680
17681 if($Location!~/this/)
17682 {
17683 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017684 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017685 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017686 push(@Sentence, "(pointer)");
17687 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017688 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017689 push(@Sentence, "(reference)");
17690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017691 }
17692 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017693
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017694 if($Location eq "this") {
17695 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17696 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017697 else
17698 {
17699 my $Location_T = $Location;
17700 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17701
17702 my $TypeID_Problem = $TypeID;
17703 if($Location_T) {
17704 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17705 }
17706
17707 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17708 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17709 }
17710 else {
17711 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017713 }
17714 }
17715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017716 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017717 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 +040017718 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017719
17720 my $Sent = join(" ", @Sentence);
17721
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017722 $Sent=~s/->/./g;
17723
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017724 if($ReportFormat eq "xml")
17725 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017726 $Sent=~s/'//g;
17727 }
17728
17729 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017730}
17731
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017732sub getFieldType($$$)
17733{
17734 my ($Location, $TypeId, $LibVersion) = @_;
17735
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017736 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017737
17738 foreach my $Name (@Fields)
17739 {
17740 my %Info = get_BaseType($TypeId, $LibVersion);
17741
17742 foreach my $Pos (keys(%{$Info{"Memb"}}))
17743 {
17744 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17745 {
17746 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17747 last;
17748 }
17749 }
17750 }
17751
17752 return $TypeId;
17753}
17754
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017755sub get_XmlSign($$)
17756{
17757 my ($Symbol, $LibVersion) = @_;
17758 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17759 my $Report = "";
17760 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17761 {
17762 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017763 my $Type = $Info->{"Param"}{$Pos}{"type"};
17764 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017765 foreach my $Typedef (keys(%ChangedTypedef))
17766 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017767 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17768 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017770 }
17771 $Report .= " <param pos=\"$Pos\">\n";
17772 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017773 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017774 $Report .= " </param>\n";
17775 }
17776 if(my $Return = $Info->{"Return"})
17777 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017778 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017779 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017780 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017781 $Report .= " </retval>\n";
17782 }
17783 return $Report;
17784}
17785
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017786sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017787{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017788 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017789 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017790 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017791 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017792 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17793 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794 next;
17795 }
17796 $Report .= " <symbol name=\"$Symbol\">\n";
17797 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017798 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017799 {
17800 if(defined $CompleteSignature{1}{$Symbol}
17801 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17802 {
17803 $P1 = get_XmlSign($Symbol, 1);
17804 $S1 = get_Signature($Symbol, 1);
17805 }
17806 elsif($Symbol=~/\A(_Z|\?)/) {
17807 $S1 = $tr_name{$Symbol};
17808 }
17809 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017810 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017811 {
17812 if(defined $CompleteSignature{2}{$Symbol}
17813 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17814 {
17815 $P2 = get_XmlSign($Symbol, 2);
17816 $S2 = get_Signature($Symbol, 2);
17817 }
17818 elsif($Symbol=~/\A(_Z|\?)/) {
17819 $S2 = $tr_name{$Symbol};
17820 }
17821 }
17822 if($S1)
17823 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017824 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017825 $Report .= $P1;
17826 $Report .= " </old>\n";
17827 }
17828 if($S2 and $S2 ne $S1)
17829 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017830 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017831 $Report .= $P2;
17832 $Report .= " </new>\n";
17833 }
17834 $Report .= " </symbol>\n";
17835 }
17836 $Report .= "</symbols_info>\n";
17837 return $Report;
17838}
17839
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017840sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017841{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017842 my ($Level, $Report) = @_;
17843 if($ReportFormat eq "xml") {
17844 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017845 }
17846 if($StdOut)
17847 { # --stdout option
17848 print STDOUT $Report;
17849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017850 else
17851 {
17852 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017853 mkpath(get_dirname($RPath));
17854
17855 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17856 print REPORT $Report;
17857 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017858 }
17859}
17860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017861sub getReport($)
17862{
17863 my $Level = $_[0];
17864 if($ReportFormat eq "xml")
17865 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017866 if($Level eq "Join")
17867 {
17868 my $Report = "<reports>\n";
17869 $Report .= getReport("Binary");
17870 $Report .= getReport("Source");
17871 $Report .= "</reports>\n";
17872 return $Report;
17873 }
17874 else
17875 {
17876 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17877 my ($Summary, $MetaData) = get_Summary($Level);
17878 $Report .= $Summary."\n";
17879 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17880 $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 +040017881
17882 # additional symbols info (if needed)
17883 # $Report .= get_Report_SymbolsInfo($Level);
17884
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017885 $Report .= "</report>\n";
17886 return $Report;
17887 }
17888 }
17889 else
17890 { # HTML
17891 my $CssStyles = readModule("Styles", "Report.css");
17892 my $JScripts = readModule("Scripts", "Sections.js");
17893 if($Level eq "Join")
17894 {
17895 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17896 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017897 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017898 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17899 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 +040017900 my ($BSummary, $BMetaData) = get_Summary("Binary");
17901 my ($SSummary, $SMetaData) = get_Summary("Source");
17902 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 +030017903 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017904 <br/>
17905 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017906 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17907 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017908 </div>";
17909 $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>";
17910 $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 +030017911 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017912 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017913 return $Report;
17914 }
17915 else
17916 {
17917 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017918 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17919 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17920 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 +040017921 if($Level eq "Binary")
17922 {
17923 if(getArch(1) eq getArch(2)
17924 and getArch(1) ne "unknown") {
17925 $Description .= " on ".showArch(getArch(1));
17926 }
17927 }
17928 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 +030017929 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017930 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17931 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17932 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017933 $Report .= "</div>\n<br/><br/><br/>\n";
17934 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017935 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017936 return $Report;
17937 }
17938 }
17939}
17940
17941sub createReport()
17942{
17943 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017944 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017945 writeReport("Join", getReport("Join"));
17946 }
17947 elsif($DoubleReport)
17948 { # default
17949 writeReport("Binary", getReport("Binary"));
17950 writeReport("Source", getReport("Source"));
17951 }
17952 elsif($BinaryOnly)
17953 { # --binary
17954 writeReport("Binary", getReport("Binary"));
17955 }
17956 elsif($SourceOnly)
17957 { # --source
17958 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017959 }
17960}
17961
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017962sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017963{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017964 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017965
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017966 $Footer .= "<hr/>\n";
17967 $Footer .= "<div class='footer' align='right'>";
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030017968 $Footer .= "<i>Generated by <a href='".$HomePage{"Dev"}."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017969 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017970 $Footer .= "<br/>\n";
17971
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017972 return $Footer;
17973}
17974
17975sub get_Report_Problems($$)
17976{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017977 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017978
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017979 my $Report = get_Report_TypeProblems($Severity, $Level);
17980 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017981 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017982 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017983
17984 if($Severity eq "Low" or $Severity eq "Safe") {
17985 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017986 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017987
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017988 if($ReportFormat eq "html")
17989 {
17990 if($Report)
17991 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017992 if($JoinReport)
17993 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017994 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017995 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17996 }
17997 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017998 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018000 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018001 else
18002 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018003 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018004 $Report = "<a name=\'Other_Changes\'></a>".$Report;
18005 }
18006 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018007 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018009 }
18010 }
18011 }
18012 return $Report;
18013}
18014
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018015sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018016{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018017 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030018018
18019 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
18020 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
18021 $Head .= "<head>\n";
18022 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
18023 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
18024 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
18025 $Head .= "<title>$Title</title>\n";
18026 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
18027 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
18028 $Head .= "</head>\n";
18029
18030 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018031}
18032
18033sub insertIDs($)
18034{
18035 my $Text = $_[0];
18036 while($Text=~/CONTENT_ID/)
18037 {
18038 if(int($Content_Counter)%2) {
18039 $ContentID -= 1;
18040 }
18041 $Text=~s/CONTENT_ID/c_$ContentID/;
18042 $ContentID += 1;
18043 $Content_Counter += 1;
18044 }
18045 return $Text;
18046}
18047
18048sub checkPreprocessedUnit($)
18049{
18050 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018051 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018052 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018053 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018054
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018055 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018056 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018057 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018058 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018059 chomp($Line);
18060 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018061 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018062 $CurHeader = path_format($1, $OSgroup);
18063 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018064 $CurClass = "";
18065
18066 if(index($CurHeader, $TMP_DIR)==0) {
18067 next;
18068 }
18069
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018070 if(substr($CurHeaderName, 0, 1) eq "<")
18071 { # <built-in>, <command-line>, etc.
18072 $CurHeaderName = "";
18073 $CurHeader = "";
18074 }
18075
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018076 if($ExtraInfo)
18077 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018078 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018079 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18080 }
18081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018082 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018083 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018084 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018085 if($CurHeaderName)
18086 {
18087 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18088 and not $Registered_Headers{$Version}{$CurHeader})
18089 { # not a target
18090 next;
18091 }
18092 if(not is_target_header($CurHeaderName, 1)
18093 and not is_target_header($CurHeaderName, 2))
18094 { # user-defined header
18095 next;
18096 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018097 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018098 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018099
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018100 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018101 {
18102 my ($Name, $Value) = ($1, $2);
18103 if(not $Constants{$Version}{$Name}{"Access"})
18104 {
18105 $Constants{$Version}{$Name}{"Access"} = "public";
18106 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018107 if($CurHeaderName) {
18108 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18109 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018110 }
18111 }
18112 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18113 $Constants{$Version}{$1}{"Access"} = "private";
18114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018115 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018116 else
18117 {
18118 if(defined $ExtraDump)
18119 {
18120 if($Line=~/(\w+)\s*\(/)
18121 { # functions
18122 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18123 }
18124 #elsif($Line=~/(\w+)\s*;/)
18125 #{ # data
18126 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18127 #}
18128 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18129 $CurClass = $2;
18130 }
18131 }
18132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018133 }
18134 close(PREPROC);
18135 foreach my $Constant (keys(%{$Constants{$Version}}))
18136 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018137 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18138 {
18139 delete($Constants{$Version}{$Constant});
18140 next;
18141 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018142 if(not $ExtraDump and ($Constant=~/_h\Z/i
18143 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018144 { # skip
18145 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018146 }
18147 else {
18148 delete($Constants{$Version}{$Constant}{"Access"});
18149 }
18150 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018151 if($Debug)
18152 {
18153 mkpath($DEBUG_PATH{$Version});
18154 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018156}
18157
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018158sub uncoverConstant($$)
18159{
18160 my ($LibVersion, $Constant) = @_;
18161 return "" if(not $LibVersion or not $Constant);
18162 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18163 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18164 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18165 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018166
18167 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018168 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018169 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18170 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018171 {
18172 push(@RecurConstant, $Constant);
18173 my $Uncovered = uncoverConstant($LibVersion, $Value);
18174 if($Uncovered ne "") {
18175 $Value = $Uncovered;
18176 }
18177 pop(@RecurConstant);
18178 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018179
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018180 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018181 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018182 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18183 }
18184 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18185}
18186
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018187sub simpleConstant($$)
18188{
18189 my ($LibVersion, $Value) = @_;
18190 if($Value=~/\W/)
18191 {
18192 my $Value_Copy = $Value;
18193 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18194 {
18195 my $Word = $1;
18196 if($Value!~/$Word\s*\(/)
18197 {
18198 my $Val = uncoverConstant($LibVersion, $Word);
18199 if($Val ne "")
18200 {
18201 $Value=~s/\b$Word\b/$Val/g;
18202 }
18203 }
18204 }
18205 }
18206 return $Value;
18207}
18208
18209sub computeValue($)
18210{
18211 my $Value = $_[0];
18212
18213 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18214 return $1;
18215 }
18216
18217 if($Value=~/\A[\d\-\+()]+\Z/) {
18218 return eval($Value);
18219 }
18220
18221 return $Value;
18222}
18223
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018224my %IgnoreConstant = map {$_=>1} (
18225 "VERSION",
18226 "VERSIONCODE",
18227 "VERNUM",
18228 "VERS_INFO",
18229 "PATCHLEVEL",
18230 "INSTALLPREFIX",
18231 "VBUILD",
18232 "VPATCH",
18233 "VMINOR",
18234 "BUILD_STRING",
18235 "BUILD_TIME",
18236 "PACKAGE_STRING",
18237 "PRODUCTION",
18238 "CONFIGURE_COMMAND",
18239 "INSTALLDIR",
18240 "BINDIR",
18241 "CONFIG_FILE_PATH",
18242 "DATADIR",
18243 "EXTENSION_DIR",
18244 "INCLUDE_PATH",
18245 "LIBDIR",
18246 "LOCALSTATEDIR",
18247 "SBINDIR",
18248 "SYSCONFDIR",
18249 "RELEASE",
18250 "SOURCE_ID",
18251 "SUBMINOR",
18252 "MINOR",
18253 "MINNOR",
18254 "MINORVERSION",
18255 "MAJOR",
18256 "MAJORVERSION",
18257 "MICRO",
18258 "MICROVERSION",
18259 "BINARY_AGE",
18260 "INTERFACE_AGE",
18261 "CORE_ABI",
18262 "PATCH",
18263 "COPYRIGHT",
18264 "TIMESTAMP",
18265 "REVISION",
18266 "PACKAGE_TAG",
18267 "PACKAGEDATE",
18268 "NUMVERSION",
18269 "Release",
18270 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018271);
18272
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018273sub constantFilter($$$)
18274{
18275 my ($Name, $Value, $Level) = @_;
18276
18277 if($Level eq "Binary")
18278 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018279 if($Name=~/_t\Z/)
18280 { # __malloc_ptr_t
18281 return 1;
18282 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018283 foreach (keys(%IgnoreConstant))
18284 {
18285 if($Name=~/(\A|_)$_(_|\Z)/)
18286 { # version
18287 return 1;
18288 }
18289 if(/\A[A-Z].*[a-z]\Z/)
18290 {
18291 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18292 { # version
18293 return 1;
18294 }
18295 }
18296 }
18297 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18298 { # version
18299 return 1;
18300 }
18301 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18302 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18303 return 1;
18304 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018305
18306 if($Value=~/\A["'].*['"]/i)
18307 { # string
18308 return 0;
18309 }
18310
18311 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18312 { # static int gcry_pth_init
18313 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018314 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018315 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018316 return 1;
18317 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018318 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018319 { # foo(p)
18320 return 1;
18321 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018322 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018323 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018324 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018325 return 1;
18326 }
18327 }
18328
18329 return 0;
18330}
18331
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018332sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018333{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018334 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018335 foreach my $Constant (keys(%{$Constants{1}}))
18336 {
18337 if($SkipConstants{1}{$Constant})
18338 { # skipped by the user
18339 next;
18340 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018341
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018342 if(my $Header = $Constants{1}{$Constant}{"Header"})
18343 {
18344 if(not is_target_header($Header, 1)
18345 and not is_target_header($Header, 2))
18346 { # user-defined header
18347 next;
18348 }
18349 }
18350 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018351 next;
18352 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018353
18354 my $Old_Value = uncoverConstant(1, $Constant);
18355
18356 if(constantFilter($Constant, $Old_Value, $Level))
18357 { # separate binary and source problems
18358 next;
18359 }
18360
18361 if(not defined $Constants{2}{$Constant}{"Value"})
18362 { # removed
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018363 if(not defined $SkipRemovedConstants)
18364 {
18365 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18366 "Target"=>$Constant,
18367 "Old_Value"=>$Old_Value );
18368 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018369 next;
18370 }
18371
18372 if($Constants{2}{$Constant}{"Value"} eq "")
18373 { # empty value
18374 # TODO: implement a rule
18375 next;
18376 }
18377
18378 my $New_Value = uncoverConstant(2, $Constant);
18379
18380 my $Old_Value_Pure = $Old_Value;
18381 my $New_Value_Pure = $New_Value;
18382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018383 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18384 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18385 $New_Value_Pure=~s/(\W)\s+/$1/g;
18386 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018388 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018389
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018390 if($New_Value_Pure ne $Old_Value_Pure)
18391 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018392 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18393 { # complex values
18394 next;
18395 }
18396 if(computeValue($Old_Value) eq computeValue($New_Value))
18397 { # expressions
18398 next;
18399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018400 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18401 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18402 next;
18403 }
18404 if($Old_Value eq "0" and $New_Value eq "NULL")
18405 { # 0 => NULL
18406 next;
18407 }
18408 if($Old_Value eq "NULL" and $New_Value eq "0")
18409 { # NULL => 0
18410 next;
18411 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018412 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018413 "Target"=>$Constant,
18414 "Old_Value"=>$Old_Value,
18415 "New_Value"=>$New_Value );
18416 }
18417 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018418
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018419 if(defined $SkipAddedConstants) {
18420 return;
18421 }
18422
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018423 foreach my $Constant (keys(%{$Constants{2}}))
18424 {
18425 if(not defined $Constants{1}{$Constant}{"Value"})
18426 {
18427 if($SkipConstants{2}{$Constant})
18428 { # skipped by the user
18429 next;
18430 }
18431
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018432 if(my $Header = $Constants{2}{$Constant}{"Header"})
18433 {
18434 if(not is_target_header($Header, 1)
18435 and not is_target_header($Header, 2))
18436 { # user-defined header
18437 next;
18438 }
18439 }
18440 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018441 next;
18442 }
18443
18444 my $New_Value = uncoverConstant(2, $Constant);
18445 if(not defined $New_Value or $New_Value eq "") {
18446 next;
18447 }
18448
18449 if(constantFilter($Constant, $New_Value, $Level))
18450 { # separate binary and source problems
18451 next;
18452 }
18453
18454 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18455 "Target"=>$Constant,
18456 "New_Value"=>$New_Value );
18457 }
18458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018459}
18460
18461sub convert_integer($)
18462{
18463 my $Value = $_[0];
18464 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018465 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018466 return hex($Value);
18467 }
18468 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018469 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018470 return oct($Value);
18471 }
18472 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018473 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018474 return oct($Value);
18475 }
18476 else {
18477 return $Value;
18478 }
18479}
18480
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018481sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018482{
18483 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018484 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018485 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018486 {
18487 if($LibVersion==1)
18488 {
18489 printMsg("WARNING", "checking headers only");
18490 $CheckHeadersOnly = 1;
18491 }
18492 else {
18493 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18494 }
18495 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018496
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018497 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018498 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018500
18501 if($CheckUndefined)
18502 {
18503 my %UndefinedLibs = ();
18504
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018505 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18506
18507 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018508 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018509 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018510 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018511 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018512 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018513 if($Symbol_Library{$LibVersion}{$Symbol}
18514 or $DepSymbol_Library{$LibVersion}{$Symbol})
18515 { # exported by target library
18516 next;
18517 }
18518 if(index($Symbol, '@')!=-1)
18519 { # exported default symbol version (@@)
18520 $Symbol=~s/\@/\@\@/;
18521 if($Symbol_Library{$LibVersion}{$Symbol}
18522 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18523 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018524 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018525 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018526 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18527 $UndefinedLibs{$Path} = 1;
18528 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018529 }
18530 }
18531 }
18532 if($ExtraInfo)
18533 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018534 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018535 {
18536 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018537 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018538 foreach (@Paths)
18539 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018540 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018541 my ($Dir, $Name) = separate_path($_);
18542
18543 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018544 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018545 }
18546
18547 $Name = parse_libname($Name, "name", $OStarget);
18548 $Name=~s/\Alib//;
18549
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018550 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018551 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018552
18553 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18554 {
18555 $LibString = " -L".esc($Dir).$LibString;
18556 }
18557
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018558 writeFile($ExtraInfo."/libs-string", $LibString);
18559 }
18560 }
18561 }
18562
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018563 if($ExtraInfo) {
18564 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18565 }
18566
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018567 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018568 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018569 if($#LibPaths!=-1)
18570 {
18571 if(not keys(%{$Symbol_Library{$LibVersion}}))
18572 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018573 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018574 printMsg("WARNING", "checking headers only");
18575 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018576 }
18577 }
18578 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018579
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018580 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018581 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018582}
18583
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018584my %Prefix_Lib_Map=(
18585 # symbols for autodetecting library dependencies (by prefix)
18586 "pthread_" => ["libpthread"],
18587 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18588 "cairo_" => ["libcairo"],
18589 "gtk_" => ["libgtk-x11-2.0"],
18590 "atk_" => ["libatk-1.0"],
18591 "gdk_" => ["libgdk-x11-2.0"],
18592 "gl" => ["libGL"],
18593 "glu" => ["libGLU"],
18594 "popt" => ["libpopt"],
18595 "Py" => ["libpython"],
18596 "jpeg_" => ["libjpeg"],
18597 "BZ2_" => ["libbz2"],
18598 "Fc" => ["libfontconfig"],
18599 "Xft" => ["libXft"],
18600 "SSL_" => ["libssl"],
18601 "sem_" => ["libpthread"],
18602 "snd_" => ["libasound"],
18603 "art_" => ["libart_lgpl_2"],
18604 "dbus_g" => ["libdbus-glib-1"],
18605 "GOMP_" => ["libgomp"],
18606 "omp_" => ["libgomp"],
18607 "cms" => ["liblcms"]
18608);
18609
18610my %Pattern_Lib_Map=(
18611 "SL[a-z]" => ["libslang"]
18612);
18613
18614my %Symbol_Lib_Map=(
18615 # symbols for autodetecting library dependencies (by name)
18616 "pow" => "libm",
18617 "fmod" => "libm",
18618 "sin" => "libm",
18619 "floor" => "libm",
18620 "cos" => "libm",
18621 "dlopen" => "libdl",
18622 "deflate" => "libz",
18623 "inflate" => "libz",
18624 "move_panel" => "libpanel",
18625 "XOpenDisplay" => "libX11",
18626 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018627 "clock_gettime" => "librt",
18628 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018629);
18630
18631sub find_SymbolLibs($$)
18632{
18633 my ($LibVersion, $Symbol) = @_;
18634
18635 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18636 { # debug symbols
18637 return ();
18638 }
18639
18640 my %Paths = ();
18641
18642 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18643 {
18644 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18645 $Paths{$Path} = 1;
18646 }
18647 }
18648
18649 if(my $SymbolPrefix = getPrefix($Symbol))
18650 {
18651 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18652 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18653 }
18654
18655 if(not keys(%Paths))
18656 {
18657 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18658 {
18659 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18660 {
18661 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18662 $Paths{$Path} = 1;
18663 }
18664 }
18665 }
18666 }
18667
18668 if(not keys(%Paths))
18669 {
18670 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18671 {
18672 if($Symbol=~/\A$Prefix/)
18673 {
18674 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18675 {
18676 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18677 $Paths{$Path} = 1;
18678 }
18679 }
18680 }
18681 }
18682 }
18683
18684 if(not keys(%Paths))
18685 {
18686 if($SymbolPrefix)
18687 { # try to find a library by symbol prefix
18688 if($SymbolPrefix eq "inotify" and
18689 index($Symbol, "\@GLIBC")!=-1)
18690 {
18691 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18692 $Paths{$Path} = 1;
18693 }
18694 }
18695 else
18696 {
18697 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18698 $Paths{$Path} = 1;
18699 }
18700 }
18701 }
18702 }
18703
18704 if(my @Paths = keys(%Paths)) {
18705 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18706 }
18707 }
18708 return keys(%Paths);
18709}
18710
18711sub get_LibPath_Prefix($$)
18712{
18713 my ($LibVersion, $Prefix) = @_;
18714
18715 $Prefix = lc($Prefix);
18716 $Prefix=~s/[_]+\Z//g;
18717
18718 foreach ("-2", "2", "-1", "1", "")
18719 { # libgnome-2.so
18720 # libxml2.so
18721 # libdbus-1.so
18722 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18723 return $Path;
18724 }
18725 }
18726 return "";
18727}
18728
18729sub getPrefix($)
18730{
18731 my $Str = $_[0];
18732 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18733 { # XmuValidArea: Xmu
18734 return $1;
18735 }
18736 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18737 { # snfReadFont: snf
18738 return $1;
18739 }
18740 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18741 { # XRRTimes: XRR
18742 return $1;
18743 }
18744 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18745 { # H5HF_delete: H5
18746 return $1;
18747 }
18748 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18749 { # alarm_event_add: alarm_
18750 return $1;
18751 }
18752 elsif($Str=~/\A(([a-z])\2{1,})/i)
18753 { # ffopen
18754 return $1;
18755 }
18756 return "";
18757}
18758
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018759sub getSymbolSize($$)
18760{ # size from the shared library
18761 my ($Symbol, $LibVersion) = @_;
18762 return 0 if(not $Symbol);
18763 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18764 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18765 {
18766 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18767 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18768 {
18769 if($Size<0) {
18770 return -$Size;
18771 }
18772 }
18773 }
18774 return 0;
18775}
18776
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018777sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018778{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18779 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018780 my ($Name, $Type) = @_;
18781
18782 # single
18783 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018784 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018785 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018786 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018787 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018788
18789 # double
18790 if($Name=~/$DEFAULT_STD_PARMS/)
18791 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018792 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018793 {
18794 my ($ShortName, $FuncParams) = split_Signature($Name);
18795
18796 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18797 {
18798 if(index($FParam, "<")!=-1)
18799 {
18800 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18801 my $FParam_N = canonifyName($FParam, "T");
18802 if($FParam_N ne $FParam) {
18803 $Name=~s/\Q$FParam\E/$FParam_N/g;
18804 }
18805 }
18806 }
18807 }
18808 elsif($Type eq "T")
18809 {
18810 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18811
18812 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018813 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018814 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018815 my $FParam = $TParams[0];
18816 foreach my $Pos (1 .. $#TParams)
18817 {
18818 my $TParam = $TParams[$Pos];
18819 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18820 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18821 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018822 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018823 }
18824 }
18825 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018826 if($Type eq "S") {
18827 return formatName($Name, "S");
18828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 return $Name;
18830}
18831
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018832sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018833{
18834 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018835 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018836 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018837 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018838 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018839 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018840 next if($tr_name{$Symbol});
18841 $Symbol=~s/[\@\$]+(.*)\Z//;
18842 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018843 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018844 elsif(index($Symbol, "?")==0)
18845 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018846 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 }
18848 else
18849 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018850 $tr_name{$Symbol} = $Symbol;
18851 $mangled_name_gcc{$Symbol} = $Symbol;
18852 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 }
18854 }
18855 if($#MnglNames1 > -1)
18856 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018857 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018858 foreach my $MnglName (@MnglNames1)
18859 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018860 if(my $Unmangled = pop(@UnmangledNames))
18861 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018862 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018863 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18864 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18865 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018866 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018867 and $tr_name{$MnglName}=~/vtable for (.+)/)
18868 { # bind class name and v-table symbol
18869 my $ClassName = $1;
18870 $ClassVTable{$ClassName} = $MnglName;
18871 $VTableClass{$MnglName} = $ClassName;
18872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018873 }
18874 }
18875 }
18876 if($#MnglNames2 > -1)
18877 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018878 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018879 foreach my $MnglName (@MnglNames2)
18880 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018881 if(my $Unmangled = pop(@UnmangledNames))
18882 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018883 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018884 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 }
18887 }
18888 return \%tr_name;
18889}
18890
18891sub link_symbol($$$)
18892{
18893 my ($Symbol, $RunWith, $Deps) = @_;
18894 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18895 return 1;
18896 }
18897 if($Deps eq "+Deps")
18898 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018899 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018900 return 1;
18901 }
18902 }
18903 return 0;
18904}
18905
18906sub link_symbol_internal($$$)
18907{
18908 my ($Symbol, $RunWith, $Where) = @_;
18909 return 0 if(not $Where or not $Symbol);
18910 if($Where->{$RunWith}{$Symbol})
18911 { # the exact match by symbol name
18912 return 1;
18913 }
18914 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18915 { # indirect symbol version, i.e.
18916 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018917 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018918 if($Where->{$RunWith}{$VSym}) {
18919 return 1;
18920 }
18921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018922 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018923 if($Sym and $Ver)
18924 { # search for the symbol with the same version
18925 # or without version
18926 if($Where->{$RunWith}{$Sym})
18927 { # old: foo@v|foo@@v
18928 # new: foo
18929 return 1;
18930 }
18931 if($Where->{$RunWith}{$Sym."\@".$Ver})
18932 { # old: foo|foo@@v
18933 # new: foo@v
18934 return 1;
18935 }
18936 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18937 { # old: foo|foo@v
18938 # new: foo@@v
18939 return 1;
18940 }
18941 }
18942 return 0;
18943}
18944
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018945sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018946{
18947 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018948 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018949 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018950 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018951 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018952 my $NM = get_CmdPath("nm");
18953 if(not $NM) {
18954 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018955 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018956 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018957 while(<APP>)
18958 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018959 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018960 push(@Imported, $1);
18961 }
18962 }
18963 close(APP);
18964 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018965 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018966 {
18967 my $DumpBinCmd = get_CmdPath("dumpbin");
18968 if(not $DumpBinCmd) {
18969 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18970 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018971 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018972 while(<APP>)
18973 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018974 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18975 push(@Imported, $1);
18976 }
18977 }
18978 close(APP);
18979 }
18980 else
18981 {
18982 my $ReadelfCmd = get_CmdPath("readelf");
18983 if(not $ReadelfCmd) {
18984 exitStatus("Not_Found", "can't find \"readelf\"");
18985 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018986 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018987 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018988 while(<APP>)
18989 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018990 if(defined $symtab)
18991 { # do nothing with symtab
18992 if(index($_, "'.dynsym'")!=-1)
18993 { # dynamic table
18994 $symtab = undef;
18995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018996 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018997 elsif(index($_, "'.symtab'")!=-1)
18998 { # symbol table
18999 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019000 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019002 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
19004 if($Ndx eq "UND")
19005 { # only imported symbols
19006 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 }
19008 }
19009 }
19010 close(APP);
19011 }
19012 return @Imported;
19013}
19014
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019015my %ELF_BIND = map {$_=>1} (
19016 "WEAK",
19017 "GLOBAL"
19018);
19019
19020my %ELF_TYPE = map {$_=>1} (
19021 "FUNC",
19022 "IFUNC",
19023 "OBJECT",
19024 "COMMON"
19025);
19026
19027my %ELF_VIS = map {$_=>1} (
19028 "DEFAULT",
19029 "PROTECTED"
19030);
19031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019032sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019033{ # read the line of 'readelf' output corresponding to the symbol
19034 my @Info = split(/\s+/, $_[0]);
19035 # Num: Value Size Type Bind Vis Ndx Name
19036 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019037 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019038 shift(@Info); # spaces
19039 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019040
19041 if($#Info==7)
19042 { # UND SYMBOL (N)
19043 if($Info[7]=~/\(\d+\)/) {
19044 pop(@Info);
19045 }
19046 }
19047
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019048 if($#Info!=6)
19049 { # other lines
19050 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019051 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019052 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019053 return () if(not defined $ELF_BIND{$Info[3]});
19054 return () if(not defined $ELF_VIS{$Info[4]});
19055 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19056 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19057 return ();
19058 }
19059 if($OStarget eq "symbian")
19060 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19061 if(index($Info[6], "_._.absent_export_")!=-1)
19062 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19063 return ();
19064 }
19065 $Info[6]=~s/\@.+//g; # remove version
19066 }
19067 if(index($Info[2], "0x") == 0)
19068 { # size == 0x3d158
19069 $Info[2] = hex($Info[2]);
19070 }
19071 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072}
19073
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019074sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019075{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019076 my ($LibVersion, $Name) = @_;
19077 return "" if(not $LibVersion or not $Name);
19078 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19079 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019080 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19082}
19083
19084sub get_LibPath_I($$)
19085{
19086 my ($LibVersion, $Name) = @_;
19087 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019088 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019089 if(-f $Name)
19090 { # absolute path
19091 return $Name;
19092 }
19093 else
19094 { # broken
19095 return "";
19096 }
19097 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019098 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019099 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019100 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019101 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019102 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019103 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019104 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019105 }
19106 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19107 { # ldconfig default paths
19108 return $DefaultPath;
19109 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019110 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019111 { # search in default linker directories
19112 # and then in all system paths
19113 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019114 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019115 }
19116 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019117 if(not defined $Cache{"checkSystemFiles"}) {
19118 checkSystemFiles();
19119 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019120 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19121 return $AllObjects[0];
19122 }
19123 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19124 {
19125 if($ShortName ne $Name)
19126 { # FIXME: check this case
19127 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19128 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019129 }
19130 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019132 # can't find
19133 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019134}
19135
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019136sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019138 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19139 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019140
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019141 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019142
19143 if(not $Real_Path)
19144 { # broken link
19145 return ();
19146 }
19147
19148 my $Lib_Name = get_filename($Real_Path);
19149
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019150 if($ExtraInfo)
19151 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019152 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019153 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019154 }
19155
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019156 if($IsNeededLib)
19157 {
19158 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19159 return ();
19160 }
19161 }
19162 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019163 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019164
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 push(@RecurLib, $Lib_Name);
19166 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019167 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19168
19169 if(not $IsNeededLib)
19170 { # special cases: libstdc++ and libc
19171 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19172 {
19173 if($ShortName eq "libstdc++")
19174 { # libstdc++.so.6
19175 $STDCXX_TESTING = 1;
19176 }
19177 elsif($ShortName eq "libc")
19178 { # libc-2.11.3.so
19179 $GLIBC_TESTING = 1;
19180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 }
19182 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019183 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019184 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019185 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019186 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019187 mkpath(get_dirname($DebugPath));
19188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019189 if($OStarget eq "macos")
19190 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019191 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019192 if(not $NM) {
19193 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019194 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019195 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019196 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019197 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019198 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019199 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019200 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019201 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019202 else
19203 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019204 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019206 while(<LIB>)
19207 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019208 if($CheckUndefined)
19209 {
19210 if(not $IsNeededLib)
19211 {
19212 if(/ U _([\w\$]+)\s*\Z/)
19213 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019214 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019215 next;
19216 }
19217 }
19218 }
19219
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019220 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019221 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019222 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019223 if($IsNeededLib)
19224 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019225 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019226 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019227 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19228 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019231 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019233 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19234 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019235 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19236 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019237 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019238 setLanguage($LibVersion, "C++");
19239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019241 }
19242 }
19243 }
19244 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019245
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019246 if($Deps)
19247 {
19248 if($LIB_TYPE eq "dynamic")
19249 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019250
19251 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019252 if(not $OtoolCmd) {
19253 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019254 }
19255
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019256 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19257 while(<LIB>)
19258 {
19259 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19260 and $1 ne $Lib_Path) {
19261 $NeededLib{$1} = 1;
19262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019263 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019264 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019266 }
19267 }
19268 elsif($OStarget eq "windows")
19269 { # Windows *.dll, *.lib
19270 my $DumpBinCmd = get_CmdPath("dumpbin");
19271 if(not $DumpBinCmd) {
19272 exitStatus("Not_Found", "can't find \"dumpbin\"");
19273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019274 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019275 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019276 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019277 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019278 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019279 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019280 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019281 else
19282 { # write to pipe
19283 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019285 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019286 {
19287 my $realname = undef;
19288 if($LIB_TYPE eq "dynamic")
19289 {
19290 # 1197 4AC 0000A620 SetThreadStackGuarantee
19291 # 1198 4AD SetThreadToken (forwarded to ...)
19292 # 3368 _o2i_ECPublicKey
19293 # 1 0 00005B30 ??0?N = ... (with pdb)
19294 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19295 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19296 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19297 { # dynamic, static and forwarded symbols
19298 $realname = $1;
19299 }
19300 }
19301 else
19302 { # static
19303 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19304 {
19305 # 16 IID_ISecurityInformation
19306 $realname = $1;
19307 }
19308 }
19309
19310 if($realname)
19311 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019312 if($IsNeededLib)
19313 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019314 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019315 {
19316 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19317 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019319 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019320 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019321 {
19322 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19323 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019324 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19325 {
19326 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19327 setLanguage($LibVersion, "C++");
19328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019330 }
19331 }
19332 }
19333 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019334
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019335 if($Deps)
19336 {
19337 if($LIB_TYPE eq "dynamic")
19338 { # dependencies
19339 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19340 while(<LIB>)
19341 {
19342 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19343 and $1 ne $Lib_Path) {
19344 $NeededLib{path_format($1, $OSgroup)} = 1;
19345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019346 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019347 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019349 }
19350 }
19351 else
19352 { # Unix; *.so, *.a
19353 # Symbian: *.dso, *.lib
19354 my $ReadelfCmd = get_CmdPath("readelf");
19355 if(not $ReadelfCmd) {
19356 exitStatus("Not_Found", "can't find \"readelf\"");
19357 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019358 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019359 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019360 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019361 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019362 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019363 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019364 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019365 else
19366 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019367 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019368 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019369 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019370 while(<LIB>)
19371 {
19372 if($LIB_TYPE eq "dynamic")
19373 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019374 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019375 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019376 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019377 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019378 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019379 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019380 # do nothing with symtab
19381 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019382 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019383 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019385 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386 next;
19387 }
19388 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019389 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019391 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019392 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019393 if($CheckUndefined)
19394 {
19395 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019396 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019397 }
19398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 next;
19400 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019401 if($Bind eq "WEAK")
19402 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019403 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019404 if($Weak eq "-Weak")
19405 { # skip WEAK symbols
19406 next;
19407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019408 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019409 my $Short = $Symbol;
19410 $Short=~s/\@.+//g;
19411 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019412 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019413 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19414 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019415 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019416 if($IsNeededLib)
19417 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019418 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019419 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019420 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19421 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019423 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019424 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019425 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019426 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19427 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19428 if($Vers)
19429 {
19430 if($LIB_EXT eq "so")
19431 { # value
19432 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19433 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019435 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019436 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19437 {
19438 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19439 setLanguage($LibVersion, "C++");
19440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 }
19443 }
19444 }
19445 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019446
19447 if($Deps and $LIB_TYPE eq "dynamic")
19448 { # dynamic library specifics
19449 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19450 open(LIB, $Cmd." |");
19451
19452 while(<LIB>)
19453 {
19454 if(/NEEDED.+\[([^\[\]]+)\]/)
19455 { # dependencies:
19456 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19457 $NeededLib{$1} = 1;
19458 }
19459 }
19460
19461 close(LIB);
19462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019464 if($Vers)
19465 {
19466 if(not $IsNeededLib and $LIB_EXT eq "so")
19467 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019468 my %Found = ();
19469
19470 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019471 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019472 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019473 next if(index($Symbol,"\@")==-1);
19474 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019475 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019476 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019477 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019478 if($Symbol_SameValue ne $Symbol
19479 and index($Symbol_SameValue,"\@")==-1)
19480 {
19481 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019482 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019483 last;
19484 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019485 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019486 }
19487 }
19488
19489 # default
19490 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19491 {
19492 next if(defined $Found{$Symbol});
19493 next if(index($Symbol,"\@\@")==-1);
19494
19495 if($Symbol=~/\A([^\@]*)\@\@/
19496 and not $SymVer{$LibVersion}{$1})
19497 {
19498 $SymVer{$LibVersion}{$1} = $Symbol;
19499 $Found{$Symbol} = 1;
19500 }
19501 }
19502
19503 # non-default
19504 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19505 {
19506 next if(defined $Found{$Symbol});
19507 next if(index($Symbol,"\@")==-1);
19508
19509 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19510 and not $SymVer{$LibVersion}{$1})
19511 {
19512 $SymVer{$LibVersion}{$1} = $Symbol;
19513 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019514 }
19515 }
19516 }
19517 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019518 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019519 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019520 foreach my $DyLib (sort keys(%NeededLib))
19521 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019522 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19523
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019524 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19525 {
19526 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19527 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19528 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019530 }
19531 }
19532 pop(@RecurLib);
19533 return $Library_Symbol{$LibVersion};
19534}
19535
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019536sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019537{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019538 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019539 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019540 return keys(%Prefixes);
19541}
19542
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019543sub get_prefixes_I($$)
19544{
19545 foreach my $P (@{$_[0]})
19546 {
19547 my @Parts = reverse(split(/[\/\\]+/, $P));
19548 my $Name = $Parts[0];
19549 foreach (1 .. $#Parts)
19550 {
19551 $_[1]->{$Name}{$P} = 1;
19552 last if($_>4 or $Parts[$_] eq "include");
19553 $Name = $Parts[$_].$SLASH.$Name;
19554 }
19555 }
19556}
19557
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019558sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019559{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019560 $Cache{"checkSystemFiles"} = 1;
19561
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019562 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019563
19564 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019565 {
19566 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019567
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019568 my @Files = cmd_find($DevelPath,"f");
19569 foreach my $Link (cmd_find($DevelPath,"l"))
19570 { # add symbolic links
19571 if(-f $Link) {
19572 push(@Files, $Link);
19573 }
19574 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019575
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019576 # search for headers in /usr/lib
19577 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19578 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19579 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019580
19581 # search for libraries in /usr/lib (including symbolic links)
19582 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19583 foreach my $Path (@Libs)
19584 {
19585 my $N = get_filename($Path);
19586 $SystemObjects{$N}{$Path} = 1;
19587 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019588 }
19589 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019590
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019591 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019592 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019593 next if(not -d $DevelPath);
19594 # search for all header files in the /usr/include
19595 # with or without extension (ncurses.h, QtCore, ...)
19596 push(@SysHeaders, cmd_find($DevelPath,"f"));
19597 foreach my $Link (cmd_find($DevelPath,"l"))
19598 { # add symbolic links
19599 if(-f $Link) {
19600 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602 }
19603 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019604 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605}
19606
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019607sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019608{
19609 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019610 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019611 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19612 {
19613 if(not -e $Dest) {
19614 exitStatus("Access_Error", "can't access \'$Dest\'");
19615 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019616 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019617 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19618 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019619 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019620 }
19621 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019622 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019623}
19624
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019625sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019626{
19627 my ($Path, $LibVersion) = @_;
19628 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019629 my $Name = get_filename($Path);
19630 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 return 1;
19632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019633 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019634 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19635 return 1;
19636 }
19637 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19638 {
19639 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19640 return 1;
19641 }
19642 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019643 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019644 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019645 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019646 return 1;
19647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019648 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019649 return 1;
19650 }
19651 }
19652 return 0;
19653}
19654
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019655sub specificHeader($$)
19656{
19657 my ($Header, $Spec) = @_;
19658 my $Name = get_filename($Header);
19659
19660 if($Spec eq "windows")
19661 {# MS Windows
19662 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19663 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19664 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19665 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19666 my @Dirs = (
19667 "win32",
19668 "win64",
19669 "win",
19670 "windows",
19671 "msvcrt"
19672 ); # /gsf-win32/
19673 if(my $DIRs = join("|", @Dirs)) {
19674 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19675 }
19676 }
19677 elsif($Spec eq "macos")
19678 { # Mac OS
19679 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19680 }
19681
19682 return 0;
19683}
19684
19685sub skipAlienHeader($)
19686{
19687 my $Path = $_[0];
19688 my $Name = get_filename($Path);
19689 my $Dir = get_dirname($Path);
19690
19691 if($Tolerance=~/2/)
19692 { # 2 - skip internal headers
19693 my @Terms = (
19694 "p",
19695 "priv",
19696 "int",
19697 "impl",
19698 "implementation",
19699 "internal",
19700 "private",
19701 "old",
19702 "compat",
19703 "debug",
19704 "test",
19705 "gen"
19706 );
19707
19708 my @Dirs = (
19709 "private",
19710 "priv",
19711 "port",
19712 "impl",
19713 "internal",
19714 "detail",
19715 "details",
19716 "old",
19717 "compat",
19718 "debug",
19719 "config",
19720 "compiler",
19721 "platform",
19722 "test"
19723 );
19724
19725 if(my $TERMs = join("|", @Terms)) {
19726 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19727 }
19728 if(my $DIRs = join("|", @Dirs)) {
19729 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19730 }
19731
19732 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19733 }
19734
19735 if($Tolerance=~/1/)
19736 { # 1 - skip non-Linux headers
19737 if($OSgroup ne "windows")
19738 {
19739 if(specificHeader($Path, "windows")) {
19740 return 1;
19741 }
19742 }
19743 if($OSgroup ne "macos")
19744 {
19745 if(specificHeader($Path, "macos")) {
19746 return 1;
19747 }
19748 }
19749 }
19750
19751 # valid
19752 return 0;
19753}
19754
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019755sub skipHeader($$)
19756{
19757 my ($Path, $LibVersion) = @_;
19758 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019759 if(defined $Cache{"skipHeader"}{$Path}) {
19760 return $Cache{"skipHeader"}{$Path};
19761 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019762 if(defined $Tolerance and $Tolerance=~/1|2/)
19763 { # --tolerant
19764 if(skipAlienHeader($Path)) {
19765 return ($Cache{"skipHeader"}{$Path} = 1);
19766 }
19767 }
19768 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19769 return 0;
19770 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019771 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19772}
19773
19774sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019775{ # returns:
19776 # 1 - if header should NOT be included and checked
19777 # 2 - if header should NOT be included, but should be checked
19778 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019779 my $Name = get_filename($Path);
19780 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019781 return $Kind;
19782 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019783 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19784 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019785 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019786 if(index($Path, $D)!=-1)
19787 {
19788 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19789 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019791 }
19792 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019793 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19794 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019795 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019796 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19797 {
19798 if($Name=~/$P/) {
19799 return $Kind;
19800 }
19801 if($P=~/[\/\\]/ and $Path=~/$P/) {
19802 return $Kind;
19803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 }
19805 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019806
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019807 return 0;
19808}
19809
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019810sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019811{
19812 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019813 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019814 { # system directory
19815 return;
19816 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019817 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 { # already registered
19819 return;
19820 }
19821 foreach my $Path (find_libs($Dir,"",1))
19822 {
19823 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019824 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019825 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019826 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019827 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19828}
19829
19830sub registerObject($$)
19831{
19832 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019833
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019834 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019835 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019836 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019837 {
19838 if(my $SONAME = getSONAME($Path)) {
19839 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19840 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019841 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019842 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19843 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019844 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019845
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019846 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019847 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019848 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019849 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019850 if($ObjArch ne getArch_GCC($LibVersion))
19851 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19852 $CheckedArch{$LibVersion} = 1;
19853 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 +040019854 }
19855 }
19856 }
19857}
19858
19859sub getArch_Object($)
19860{
19861 my $Path = $_[0];
19862
19863 my %MachineType = (
19864 "14C" => "x86",
19865 "8664" => "x86_64",
19866 "1C0" => "arm",
19867 "200" => "ia64"
19868 );
19869
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019870 my %ArchName = (
19871 "s390:31-bit" => "s390",
19872 "s390:64-bit" => "s390x",
19873 "powerpc:common" => "ppc32",
19874 "powerpc:common64" => "ppc64",
19875 "i386:x86-64" => "x86_64",
19876 "mips:3000" => "mips",
19877 "sparc:v8plus" => "sparcv9"
19878 );
19879
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019880 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019881 {
19882 my $DumpbinCmd = get_CmdPath("dumpbin");
19883 if(not $DumpbinCmd) {
19884 exitStatus("Not_Found", "can't find \"dumpbin\"");
19885 }
19886
19887 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19888 my $Out = `$Cmd`;
19889
19890 if($Out=~/(\w+)\smachine/)
19891 {
19892 if(my $Type = $MachineType{uc($1)})
19893 {
19894 return $Type;
19895 }
19896 }
19897 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019898 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019899 {
19900 my $ObjdumpCmd = get_CmdPath("objdump");
19901 if(not $ObjdumpCmd) {
19902 exitStatus("Not_Found", "can't find \"objdump\"");
19903 }
19904
19905 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019906
19907 if($OSgroup eq "windows") {
19908 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19909 }
19910 else {
19911 $Cmd = "LANG=$LOCALE ".$Cmd;
19912 }
19913 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019914
19915 if($Out=~/architecture:\s+([\w\-\:]+)/)
19916 {
19917 my $Arch = $1;
19918 if($Arch=~s/\:(.+)//)
19919 {
19920 my $Suffix = $1;
19921
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019922 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019923 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019924 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019925 }
19926 }
19927
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019928 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019929 $Arch = "x86";
19930 }
19931
19932 if($Arch eq "x86-64") {
19933 $Arch = "x86_64";
19934 }
19935
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019936 if($Arch eq "ia64-elf64") {
19937 $Arch = "ia64";
19938 }
19939
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019940 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019941 }
19942 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019943 elsif($OStarget=~/macos/)
19944 {
19945 my $OtoolCmd = get_CmdPath("otool");
19946 if(not $OtoolCmd) {
19947 exitStatus("Not_Found", "can't find \"otool\"");
19948 }
19949
19950 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19951 my $Out = qx/$Cmd/;
19952
19953 if($Out=~/X86_64/i) {
19954 return "x86_64";
19955 }
19956 elsif($Out=~/X86/i) {
19957 return "x86";
19958 }
19959 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019960 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019961 {
19962 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019963 # TODO
19964 }
19965
19966 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019967}
19968
19969sub getSONAME($)
19970{
19971 my $Path = $_[0];
19972 return if(not $Path);
19973 if(defined $Cache{"getSONAME"}{$Path}) {
19974 return $Cache{"getSONAME"}{$Path};
19975 }
19976 my $ObjdumpCmd = get_CmdPath("objdump");
19977 if(not $ObjdumpCmd) {
19978 exitStatus("Not_Found", "can't find \"objdump\"");
19979 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019980 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019981 if($OSgroup eq "windows") {
19982 $SonameCmd .= " | find \"SONAME\"";
19983 }
19984 else {
19985 $SonameCmd .= " | grep SONAME";
19986 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019987 if(my $SonameInfo = `$SonameCmd`)
19988 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019989 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19990 return ($Cache{"getSONAME"}{$Path} = $1);
19991 }
19992 }
19993 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019994}
19995
19996sub getSOPaths_Dest($$)
19997{
19998 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019999 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020000 return ();
20001 }
20002 if(-f $Dest)
20003 {
20004 if(not parse_libname($Dest, "name", $OStarget)) {
20005 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
20006 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020007 registerObject($Dest, $LibVersion);
20008 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020009 return ($Dest);
20010 }
20011 elsif(-d $Dest)
20012 {
20013 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020014 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020015 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020016 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
20017 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020018 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 { # all files and symlinks that match the name of a library
20020 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
20021 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020022 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020023 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020024 }
20025 }
20026 }
20027 else
20028 { # search for all files and symlinks
20029 foreach my $Path (find_libs($Dest,"",""))
20030 {
20031 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020032 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020033 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020034 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020035 }
20036 if($OSgroup eq "macos")
20037 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020038 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020039 {
20040 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020041 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020042 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020043 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
20044 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020045 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020046 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020047 }
20048 }
20049 }
20050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020051 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020052 }
20053 else {
20054 return ();
20055 }
20056}
20057
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020058sub realpath_F($)
20059{
20060 my $Path = $_[0];
20061 return path_format(realpath($Path), $OSgroup);
20062}
20063
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020064sub isCyclical($$)
20065{
20066 my ($Stack, $Value) = @_;
20067 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020068}
20069
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020070sub getGCC_Opts($)
20071{ # to use in module
20072 my $LibVersion = $_[0];
20073
20074 my @Opts = ();
20075
20076 if($CompilerOptions{$LibVersion})
20077 { # user-defined options
20078 push(@Opts, $CompilerOptions{$LibVersion});
20079 }
20080 if($GccOptions)
20081 { # additional
20082 push(@Opts, $GccOptions);
20083 }
20084
20085 if(@Opts) {
20086 return join(" ", @Opts);
20087 }
20088
20089 return undef;
20090}
20091
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020092sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020093{
20094 my $LibVersion = $_[0];
20095
20096 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20097 return $Cache{"getArch_GCC"}{$LibVersion};
20098 }
20099
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020100 if(not $GCC_PATH) {
20101 return undef;
20102 }
20103
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020104 my $Arch = undef;
20105
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020106 if(my $Target = get_dumpmachine($GCC_PATH))
20107 {
20108 if($Target=~/x86_64/) {
20109 $Arch = "x86_64";
20110 }
20111 elsif($Target=~/i[3-6]86/) {
20112 $Arch = "x86";
20113 }
20114 elsif($Target=~/\Aarm/i) {
20115 $Arch = "arm";
20116 }
20117 }
20118
20119 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020120 {
20121 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20122
20123 my $Cmd = $GCC_PATH." test.c -o test";
20124 if(my $Opts = getGCC_Opts($LibVersion))
20125 { # user-defined options
20126 $Cmd .= " ".$Opts;
20127 }
20128
20129 chdir($TMP_DIR);
20130 system($Cmd);
20131 chdir($ORIG_DIR);
20132
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020133 my $EX = join_P($TMP_DIR, "test");
20134
20135 if($OSgroup eq "windows") {
20136 $EX = join_P($TMP_DIR, "test.exe");
20137 }
20138
20139 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020140
20141 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020142 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020143 }
20144
20145 if(not $Arch) {
20146 exitStatus("Error", "can't check ARCH type");
20147 }
20148
20149 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20150}
20151
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020152sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020153{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020154 my $LibVersion = $_[0];
20155
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020156 my $Size = undef;
20157
20158 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020159 if(my $Arch = getArch($LibVersion))
20160 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020161 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020162 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020163 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020164 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20165 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020166 }
20167 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020168
20169 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020170 {
20171 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020172
20173 my $Cmd = $GCC_PATH." -E -dD empty.h";
20174 if(my $Opts = getGCC_Opts($LibVersion))
20175 { # user-defined options
20176 $Cmd .= " ".$Opts;
20177 }
20178
20179 chdir($TMP_DIR);
20180 my $Defines = `$Cmd`;
20181 chdir($ORIG_DIR);
20182
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020183 unlink("$TMP_DIR/empty.h");
20184
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020185 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20186 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020187 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020188 }
20189 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20190 { # GCC 3
20191 my $PTRDIFF = $1;
20192 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020193 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020194 }
20195 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020196 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020197 }
20198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020199 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020200
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020201 if(not $Size) {
20202 exitStatus("Error", "can't check WORD size");
20203 }
20204
20205 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020206}
20207
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020208sub getWordSize($)
20209{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020210 return $WORD_SIZE{$_[0]};
20211}
20212
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020213sub majorVersion($)
20214{
20215 my $V = $_[0];
20216 return 0 if(not $V);
20217 my @VParts = split(/\./, $V);
20218 return $VParts[0];
20219}
20220
20221sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020222{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020223 my ($V1, $V2) = @_;
20224 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020225 my @V1Parts = split(/\./, $V1);
20226 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020227 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20228 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020229 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20230 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20231 }
20232 return -1 if($#V1Parts < $#V2Parts);
20233 return 1 if($#V1Parts > $#V2Parts);
20234 return 0;
20235}
20236
20237sub read_ABI_Dump($$)
20238{
20239 my ($LibVersion, $Path) = @_;
20240 return if(not $LibVersion or not -e $Path);
20241 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020242 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020243 { # input *.abi
20244 $FilePath = $Path;
20245 }
20246 else
20247 { # input *.abi.tar.gz
20248 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020249 if(not isDump_U($FilePath)) {
20250 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020253
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020254 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020255
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020256 my $Line = readLineNum($FilePath, 0);
20257 if($Line=~/xml/)
20258 { # XML format
20259 loadModule("XmlDump");
20260 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020261 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020262 else
20263 { # Perl Data::Dumper format (default)
20264 open(DUMP, $FilePath);
20265 local $/ = undef;
20266 my $Content = <DUMP>;
20267 close(DUMP);
20268
20269 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20270 { # remove temp file
20271 unlink($FilePath);
20272 }
20273 if($Content!~/};\s*\Z/) {
20274 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20275 }
20276 $ABI = eval($Content);
20277 if(not $ABI) {
20278 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020280 }
20281 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020282 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020283 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020284 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020285 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020286 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020287 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020288 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020289 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020290
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020291 if($ABI->{"PublicABI"}) {
20292 $UsedDump{$LibVersion}{"Public"} = 1;
20293 }
20294
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020295 if($ABI->{"ABI_DUMP_VERSION"})
20296 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020297 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020298 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020299 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020300 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020301 }
20302 else
20303 { # support for old ABI dumps
20304 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020305 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020306 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020307 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020308 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020309
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020310 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020311 {
20312 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 +040020313 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020314
20315 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20316 { # DWARF ABI Dump
20317 $UseConv_Real{$LibVersion}{"P"} = 1;
20318 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20319
20320 $UsedDump{$LibVersion}{"DWARF"} = 1;
20321
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020322 if(not $TargetComponent_Opt)
20323 {
20324 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20325 $TargetComponent = "module";
20326 }
20327 else {
20328 $TargetComponent = "object";
20329 }
20330 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020331 }
20332
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020333 if(not checkDump($LibVersion, "2.11"))
20334 { # old ABI dumps
20335 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020336 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020337 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020338 { # ABI dump created with --binary option
20339 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20340 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020341 else
20342 { # default
20343 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20344 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020345
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020346 if(defined $ABI->{"Mode"}
20347 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020348 { # --ext option
20349 $ExtendedCheck = 1;
20350 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020351 if($ABI->{"Extra"}) {
20352 $ExtraDump = 1;
20353 }
20354
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020355 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020356 {
20357 $UsedDump{$LibVersion}{"L"} = $Lang;
20358 setLanguage($LibVersion, $Lang);
20359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020360 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020361 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020362 }
20363 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020364 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020365 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020366 if(not $TInfo)
20367 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020368 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020369 }
20370 my %Tid_TDid = ();
20371 foreach my $TDid (keys(%{$TInfo}))
20372 {
20373 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20374 {
20375 $MAX_ID = $Tid if($Tid>$MAX_ID);
20376 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020377 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020378 }
20379 }
20380 my %NewID = ();
20381 foreach my $Tid (keys(%Tid_TDid))
20382 {
20383 my @TDids = keys(%{$Tid_TDid{$Tid}});
20384 if($#TDids>=1)
20385 {
20386 foreach my $TDid (@TDids)
20387 {
20388 if($TDid) {
20389 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20390 }
20391 else
20392 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020393 my $ID = ++$MAX_ID;
20394
20395 $NewID{$TDid}{$Tid} = $ID;
20396 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20397 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020398 }
20399 }
20400 }
20401 else
20402 {
20403 my $TDid = $TDids[0];
20404 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20405 }
20406 }
20407 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20408 {
20409 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20410 if(defined $Info{"BaseType"})
20411 {
20412 my $Bid = $Info{"BaseType"}{"Tid"};
20413 my $BDid = $Info{"BaseType"}{"TDid"};
20414 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020415 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020416 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20417 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20418 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020419 }
20420 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020422 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020423 read_Machine_DumpInfo($ABI, $LibVersion);
20424 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020425 if(not $SymbolInfo{$LibVersion})
20426 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020427 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020428 }
20429 if(not keys(%{$SymbolInfo{$LibVersion}}))
20430 { # validation of old-version dumps
20431 if(not $ExtendedCheck) {
20432 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20433 }
20434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020435 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020436 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020437 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020438 else
20439 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020440 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020441 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020442 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020443 }
20444 if(not $DepSymbols)
20445 { # Cannot reconstruct DepSymbols. This may result in false
20446 # positives if the old dump is for library 2. Not a problem if
20447 # old dumps are only from old libraries.
20448 $DepSymbols = {};
20449 }
20450 foreach my $Symbol (keys(%{$DepSymbols})) {
20451 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020453 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020454 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020455
20456 if(my $V = $TargetVersion{$LibVersion}) {
20457 $Descriptor{$LibVersion}{"Version"} = $V;
20458 }
20459 else {
20460 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20461 }
20462
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020463 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020464 { # if not defined by -skip-types option
20465 if(defined $ABI->{"SkipTypes"})
20466 {
20467 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20468 {
20469 $SkipTypes{$LibVersion}{$TName} = 1;
20470 }
20471 }
20472 if(defined $ABI->{"OpaqueTypes"})
20473 { # support for old dumps
20474 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20475 {
20476 $SkipTypes{$LibVersion}{$TName} = 1;
20477 }
20478 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020479 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020480
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020481 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020482 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020483 if(defined $ABI->{"SkipSymbols"}) {
20484 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20485 }
20486 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020487 { # support for old dumps
20488 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20489 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020490 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020491 { # support for old dumps
20492 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020494 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020495 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020496
20497 if(not $TargetHeaders{$LibVersion})
20498 { # if not defined by -headers-list option
20499 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20500 }
20501
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020502 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020503 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020504 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020506 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020507 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020509
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020510 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020511 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020512
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020513 if(not checkDump($LibVersion, "2.10.1")
20514 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020515 { # support for old ABI dumps: added target headers
20516 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020517 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020519
20520 if(not $ABI->{"PublicABI"})
20521 {
20522 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20523 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20524 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020526 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020527 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020528 if(defined $ABI->{"GccConstants"})
20529 { # 3.0
20530 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20531 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20532 }
20533 }
20534
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020535 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020536 if(not $NestedNameSpaces{$LibVersion})
20537 { # support for old dumps
20538 # Cannot reconstruct NameSpaces. This may affect design
20539 # of the compatibility report.
20540 $NestedNameSpaces{$LibVersion} = {};
20541 }
20542 # target system type
20543 # needed to adopt HTML report
20544 if(not $DumpSystem)
20545 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020546 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020547 }
20548 # recreate environment
20549 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20550 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020551 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020552 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020553 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20554 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020555 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020556 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020557 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020558 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20559 {
20560 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20561 setLanguage($LibVersion, "C++");
20562 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020563 }
20564 }
20565 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020566 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20567 {
20568 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20569 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20570 }
20571 }
20572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020573 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020574 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020575 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020576 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020577 {
20578 if(not $Symbol_Library{$LibVersion}{$MnglName}
20579 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20580 push(@VFunc, $MnglName);
20581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020582 }
20583 }
20584 translateSymbols(@VFunc, $LibVersion);
20585 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020586 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20587
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020588 if(not checkDump($LibVersion, "3.0"))
20589 { # support for old ABI dumps
20590 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20591 {
20592 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20593 {
20594 if(ref($BaseType) eq "HASH") {
20595 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20596 }
20597 }
20598 }
20599 }
20600
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020601 if(not checkDump($LibVersion, "3.2"))
20602 { # support for old ABI dumps
20603 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20604 {
20605 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20606 {
20607 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20608 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20609 }
20610 }
20611 }
20612
20613 # repair target headers list
20614 delete($TargetHeaders{$LibVersion});
20615 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020616 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20617 }
20618 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20619 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020620 }
20621
20622 # non-target constants from anon enums
20623 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20624 {
20625 if(not $ExtraDump
20626 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20627 {
20628 delete($Constants{$LibVersion}{$Name});
20629 }
20630 }
20631 }
20632
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020633 if(not checkDump($LibVersion, "2.20"))
20634 { # support for old ABI dumps
20635 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20636 {
20637 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20638
20639 if($TType=~/Struct|Union|Enum|Typedef/)
20640 { # repair complex types first
20641 next;
20642 }
20643
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020644 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020645 {
20646 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20647 if($BType=~/Struct|Union|Enum/i)
20648 {
20649 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20650 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20651 }
20652 }
20653 }
20654 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20655 {
20656 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20657 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20658 if($TType=~/Struct|Union|Enum/) {
20659 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20660 }
20661 }
20662 }
20663
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020664 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020665 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020666 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20667 { # support for old ABI dumps < 2.0 (ACC 1.22)
20668 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20669 {
20670 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20671 {
20672 if($Access ne "public") {
20673 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20674 }
20675 }
20676 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20677 }
20678 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20679 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020680 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20681 { # support for old ABI dumps
20682 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20683 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020684 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20685 { # DWARF ABI Dumps
20686 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20687 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020688 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20689 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20690 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020691
20692 # support for old formatting of type names
20693 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20694
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020695 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20696 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020697 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020698 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20699 {
20700 if($SubId eq $TypeId)
20701 { # Fix erroneus ABI dump
20702 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20703 next;
20704 }
20705
20706 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020708 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020709 if($TInfo{"Type"} eq "MethodPtr")
20710 {
20711 if(defined $TInfo{"Param"})
20712 { # support for old ABI dumps <= 1.17
20713 if(not defined $TInfo{"Param"}{"0"})
20714 {
20715 my $Max = keys(%{$TInfo{"Param"}});
20716 foreach my $Pos (1 .. $Max) {
20717 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20718 }
20719 delete($TInfo{"Param"}{$Max});
20720 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20721 }
20722 }
20723 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020724 if($TInfo{"BaseType"} eq $TypeId)
20725 { # fix ABI dump
20726 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20727 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020728
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020729 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020730 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020731 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020733 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20734 if(not $BName)
20735 { # broken type
20736 next;
20737 }
20738 if($TInfo{"Name"} eq $BName)
20739 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020740 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020741 next;
20742 }
20743 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20744 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745 }
20746 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020747 }
20748 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20749 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020750 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020751 }
20752 }
20753
20754 if(not checkDump($LibVersion, "2.15"))
20755 { # support for old ABI dumps
20756 my %Dups = ();
20757 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20758 {
20759 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020761 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20762 { # remove template decls
20763 delete($SymbolInfo{$LibVersion}{$InfoId});
20764 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020766 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020767 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20768 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020769 { # templates
20770 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020771 }
20772 }
20773 }
20774
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020775 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20776 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020777 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20778 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20779 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20780 { # support for old ABI dumps (< 3.1)
20781 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20782 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20783 { # add "this" first parameter
20784 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20785 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20786
20787 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20788 {
20789 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20790 foreach my $Pos (reverse(0 .. $#Pos)) {
20791 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20792 }
20793 }
20794 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20795 }
20796 }
20797
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020798 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20799 { # ABI dumps have no mangled names for C-functions
20800 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20801 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020802 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20803 { # support for old ABI dumps
20804 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20805 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020806 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20807 { # DWARF ABI Dumps
20808 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20809 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020810 }
20811
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020812 $Descriptor{$LibVersion}{"Dump"} = 1;
20813}
20814
20815sub read_Machine_DumpInfo($$)
20816{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020817 my ($ABI, $LibVersion) = @_;
20818 if($ABI->{"Arch"}) {
20819 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020820 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020821 if($ABI->{"WordSize"}) {
20822 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020823 }
20824 else
20825 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020826 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 }
20828 if(not $WORD_SIZE{$LibVersion})
20829 { # support for old dumps (<1.23)
20830 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20831 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020832 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020833 }
20834 else
20835 {
20836 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020837 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020839 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20840 { # any "pointer"-type
20841 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020842 last;
20843 }
20844 }
20845 if($PSize)
20846 { # a pointer type size
20847 $WORD_SIZE{$LibVersion} = $PSize;
20848 }
20849 else {
20850 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20851 }
20852 }
20853 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020854 if($ABI->{"GccVersion"}) {
20855 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020856 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030020857 elsif($ABI->{"ClangVersion"}) {
20858 $CLANG_VERSION{$LibVersion} = $ABI->{"ClangVersion"};
20859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020860}
20861
20862sub read_Libs_DumpInfo($$)
20863{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020864 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020865 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20866 if(not $Library_Symbol{$LibVersion})
20867 { # support for old dumps
20868 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020870 if(keys(%{$Library_Symbol{$LibVersion}})
20871 and not $DumpAPI) {
20872 $Descriptor{$LibVersion}{"Libs"} = "OK";
20873 }
20874}
20875
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020876sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020877{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020878 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020879
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020880 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020881 and not $DumpAPI) {
20882 $Descriptor{$LibVersion}{"Headers"} = "OK";
20883 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020884 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020885 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020886 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020887 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020888 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020889
20890 if(keys(%{$ABI->{"Sources"}})
20891 and not $DumpAPI) {
20892 $Descriptor{$LibVersion}{"Sources"} = "OK";
20893 }
20894 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020895 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020896 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20897 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020899}
20900
20901sub find_libs($$$)
20902{
20903 my ($Path, $Type, $MaxDepth) = @_;
20904 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020905 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020906}
20907
20908sub createDescriptor($$)
20909{
20910 my ($LibVersion, $Path) = @_;
20911 if(not $LibVersion or not $Path
20912 or not -e $Path) {
20913 return "";
20914 }
20915 if(-d $Path)
20916 { # directory with headers files and shared objects
20917 return "
20918 <version>
20919 ".$TargetVersion{$LibVersion}."
20920 </version>
20921
20922 <headers>
20923 $Path
20924 </headers>
20925
20926 <libs>
20927 $Path
20928 </libs>";
20929 }
20930 else
20931 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020932 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020933 { # standard XML-descriptor
20934 return readFile($Path);
20935 }
20936 elsif(is_header($Path, 2, $LibVersion))
20937 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020938 $CheckHeadersOnly = 1;
20939
20940 if($LibVersion==1) {
20941 $TargetVersion{$LibVersion} = "X";
20942 }
20943
20944 if($LibVersion==2) {
20945 $TargetVersion{$LibVersion} = "Y";
20946 }
20947
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020948 return "
20949 <version>
20950 ".$TargetVersion{$LibVersion}."
20951 </version>
20952
20953 <headers>
20954 $Path
20955 </headers>
20956
20957 <libs>
20958 none
20959 </libs>";
20960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961 else
20962 { # standard XML-descriptor
20963 return readFile($Path);
20964 }
20965 }
20966}
20967
20968sub detect_lib_default_paths()
20969{
20970 my %LPaths = ();
20971 if($OSgroup eq "bsd")
20972 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020973 if(my $LdConfig = get_CmdPath("ldconfig"))
20974 {
20975 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20976 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020977 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20978 {
20979 my $Name = "lib".$1;
20980 if(not defined $LPaths{$Name}) {
20981 $LPaths{$Name} = $2;
20982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020983 }
20984 }
20985 }
20986 else {
20987 printMsg("WARNING", "can't find ldconfig");
20988 }
20989 }
20990 else
20991 {
20992 if(my $LdConfig = get_CmdPath("ldconfig"))
20993 {
20994 if($SystemRoot and $OSgroup eq "linux")
20995 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20996 if(-e $SystemRoot."/etc/ld.so.conf") {
20997 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20998 }
20999 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021000 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
21001 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021002 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
21003 {
21004 my ($Name, $Path) = ($1, $2);
21005 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021006 if(not defined $LPaths{$Name})
21007 { # get first element from the list of available paths
21008
21009 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
21010 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
21011 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
21012
21013 $LPaths{$Name} = $Path;
21014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021015 }
21016 }
21017 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040021018 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021019 printMsg("WARNING", "can't find ldconfig");
21020 }
21021 }
21022 return \%LPaths;
21023}
21024
21025sub detect_bin_default_paths()
21026{
21027 my $EnvPaths = $ENV{"PATH"};
21028 if($OSgroup eq "beos") {
21029 $EnvPaths.=":".$ENV{"BETOOLS"};
21030 }
21031 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021032 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033 {
21034 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021035 next if(not $Path);
21036 if($SystemRoot
21037 and $Path=~/\A\Q$SystemRoot\E\//)
21038 { # do NOT use binaries from target system
21039 next;
21040 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 }
21043}
21044
21045sub detect_inc_default_paths()
21046{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021047 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021049 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021050 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021051 next if(index($Line, "/cc1plus ")!=-1);
21052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021053 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
21054 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021055 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021056 if(index($Path, "c++")!=-1
21057 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021058 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021059 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021060 if(not defined $MAIN_CPP_DIR
21061 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
21062 $MAIN_CPP_DIR = $Path;
21063 }
21064 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021065 elsif(index($Path, "gcc")!=-1) {
21066 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021067 }
21068 else
21069 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021070 if($Path=~/local[\/\\]+include/)
21071 { # local paths
21072 next;
21073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074 if($SystemRoot
21075 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
21076 { # The GCC include path for user headers is not a part of the system root
21077 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
21078 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
21079 next;
21080 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021081 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021082 }
21083 }
21084 }
21085 unlink("$TMP_DIR/empty.h");
21086 return %DPaths;
21087}
21088
21089sub detect_default_paths($)
21090{
21091 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
21092 my $Search = $_[0];
21093 if($Search!~/inc/) {
21094 $HSearch = 0;
21095 }
21096 if($Search!~/lib/) {
21097 $LSearch = 0;
21098 }
21099 if($Search!~/bin/) {
21100 $BSearch = 0;
21101 }
21102 if($Search!~/gcc/) {
21103 $GSearch = 0;
21104 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021105 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021106 { # <search_headers> section of the XML descriptor
21107 # do NOT search for systems headers
21108 $HSearch = 0;
21109 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021110 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021111 { # <search_libs> section of the XML descriptor
21112 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021113 $LSearch = 0;
21114 }
21115 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21116 { # additional search paths
21117 next if($Type eq "include" and not $HSearch);
21118 next if($Type eq "lib" and not $LSearch);
21119 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021120 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021121 }
21122 if($OSgroup ne "windows")
21123 { # unix-like
21124 foreach my $Type ("include", "lib", "bin")
21125 { # automatic detection of system "devel" directories
21126 next if($Type eq "include" and not $HSearch);
21127 next if($Type eq "lib" and not $LSearch);
21128 next if($Type eq "bin" and not $BSearch);
21129 my ($UsrDir, $RootDir) = ("/usr", "/");
21130 if($SystemRoot and $Type ne "bin")
21131 { # 1. search for target headers and libraries
21132 # 2. use host commands: ldconfig, readelf, etc.
21133 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21134 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021135 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021136 if(-d $RootDir."/".$Type)
21137 { # if "/lib" is symbolic link
21138 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021139 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021140 }
21141 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021142 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 }
21144 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021145 if(-d $UsrDir)
21146 {
21147 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021148 if(-d $UsrDir."/".$Type)
21149 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021150 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021151 }
21152 }
21153 }
21154 }
21155 if($BSearch)
21156 {
21157 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021158 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 }
21160 # check environment variables
21161 if($OSgroup eq "beos")
21162 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021163 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021165 if($_ eq ".") {
21166 next;
21167 }
21168 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21169 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21170 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021171 }
21172 }
21173 if($HSearch)
21174 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021175 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21176 split(/:|;/, $ENV{"BEINCLUDES"})
21177 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021178 }
21179 if($LSearch)
21180 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021181 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21182 split(/:|;/, $ENV{"BELIBRARIES"}),
21183 split(/:|;/, $ENV{"LIBRARY_PATH"})
21184 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021185 }
21186 }
21187 if($LSearch)
21188 { # using linker to get system paths
21189 if(my $LPaths = detect_lib_default_paths())
21190 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021191 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021192 foreach my $Name (keys(%{$LPaths}))
21193 {
21194 if($SystemRoot
21195 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21196 { # wrong ldconfig configuration
21197 # check your <sysroot>/etc/ld.so.conf
21198 next;
21199 }
21200 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021201 if(my $Dir = get_dirname($LPaths->{$Name})) {
21202 $Dirs{$Dir} = 1;
21203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021204 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021205 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021206 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021207 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021208 }
21209 if($BSearch)
21210 {
21211 if($CrossGcc)
21212 { # --cross-gcc=arm-linux-gcc
21213 if(-e $CrossGcc)
21214 { # absolute or relative path
21215 $GCC_PATH = get_abs_path($CrossGcc);
21216 }
21217 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21218 { # command name
21219 $GCC_PATH = $CrossGcc;
21220 }
21221 else {
21222 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21223 }
21224 if($GCC_PATH=~/\s/) {
21225 $GCC_PATH = "\"".$GCC_PATH."\"";
21226 }
21227 }
21228 }
21229 if($GSearch)
21230 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021231 if(not $CrossGcc)
21232 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021233 $GCC_PATH = get_CmdPath("gcc");
21234 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021235 if(not $GCC_PATH)
21236 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021237 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021238 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021239 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021240 { # select the latest version
21241 @GCCs = sort {$b cmp $a} @GCCs;
21242 if(check_gcc($GCCs[0], "3"))
21243 {
21244 $GCC_PATH = $GCCs[0];
21245 last;
21246 }
21247 }
21248 }
21249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021250 if(not $GCC_PATH) {
21251 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21252 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021253
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021254 my $GCC_Ver = get_dumpversion($GCC_PATH);
21255 if($GCC_Ver eq "4.8")
21256 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21257 my $Info = `$GCC_PATH --version`;
21258
21259 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21260 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21261 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21262 $GCC_Ver = $2;
21263 }
21264 }
21265
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021266 if($OStarget=~/macos/)
21267 {
21268 my $Info = `$GCC_PATH --version`;
21269
21270 if($Info=~/clang/i) {
21271 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21272 }
21273 }
21274
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021275 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021276 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021277 my $GccTarget = get_dumpmachine($GCC_PATH);
21278
21279 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021280 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021281 $OStarget = "linux";
21282 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021283 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021284 elsif($GccTarget=~/symbian/)
21285 {
21286 $OStarget = "symbian";
21287 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21288 }
21289
21290 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21291
21292 # check GCC version
21293 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21294 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021295 # introduced in 4.8 and fixed in 4.8.3
21296 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update GCC to 4.8.3 or downgrade it to 4.7. You can use a local GCC installation by --gcc-path=PATH option.");
21297
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021298 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021299 }
21300 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021301 else {
21302 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021303 }
21304 }
21305 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021306 {
21307 # GCC standard paths
21308 if($GCC_PATH and not $NoStdInc)
21309 {
21310 my %DPaths = detect_inc_default_paths();
21311 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21312 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21313 @DefaultIncPaths = @{$DPaths{"Inc"}};
21314 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21315 }
21316
21317 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021318 my $IncPath = "/usr/include";
21319 if($SystemRoot) {
21320 $IncPath = $SystemRoot.$IncPath;
21321 }
21322 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021323 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021324 }
21325 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021326
21327 if($ExtraInfo)
21328 {
21329 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21330 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332}
21333
21334sub getLIB_EXT($)
21335{
21336 my $Target = $_[0];
21337 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21338 return $Ext;
21339 }
21340 return $OS_LibExt{$LIB_TYPE}{"default"};
21341}
21342
21343sub getAR_EXT($)
21344{
21345 my $Target = $_[0];
21346 if(my $Ext = $OS_Archive{$Target}) {
21347 return $Ext;
21348 }
21349 return $OS_Archive{"default"};
21350}
21351
21352sub get_dumpversion($)
21353{
21354 my $Cmd = $_[0];
21355 return "" if(not $Cmd);
21356 if($Cache{"get_dumpversion"}{$Cmd}) {
21357 return $Cache{"get_dumpversion"}{$Cmd};
21358 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021359 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021360 chomp($V);
21361 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21362}
21363
21364sub get_dumpmachine($)
21365{
21366 my $Cmd = $_[0];
21367 return "" if(not $Cmd);
21368 if($Cache{"get_dumpmachine"}{$Cmd}) {
21369 return $Cache{"get_dumpmachine"}{$Cmd};
21370 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021371 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021372 chomp($Machine);
21373 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21374}
21375
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021376sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021377{
21378 my $Cmd = $_[0];
21379 return "" if(not $Cmd);
21380 my @Options = (
21381 "--version",
21382 "-help"
21383 );
21384 foreach my $Opt (@Options)
21385 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021386 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021387 if($Info) {
21388 return 1;
21389 }
21390 }
21391 return 0;
21392}
21393
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021394sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021395{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021396 my ($Cmd, $ReqVer) = @_;
21397 return 0 if(not $Cmd or not $ReqVer);
21398 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21399 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021401 if(my $GccVer = get_dumpversion($Cmd))
21402 {
21403 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21404 if(cmpVersions($GccVer, $ReqVer)>=0) {
21405 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21406 }
21407 }
21408 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409}
21410
21411sub get_depth($)
21412{
21413 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021414 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021415 }
21416 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21417}
21418
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021419sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021420{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021421 return if($Cache{"registerGccHeaders"}); # this function should be called once
21422
21423 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021424 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021425 my @Headers = cmd_find($Path,"f");
21426 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21427 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021429 my $FileName = get_filename($HPath);
21430 if(not defined $DefaultGccHeader{$FileName})
21431 { # skip duplicated
21432 $DefaultGccHeader{$FileName} = $HPath;
21433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021434 }
21435 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021436 $Cache{"registerGccHeaders"} = 1;
21437}
21438
21439sub registerCppHeaders()
21440{
21441 return if($Cache{"registerCppHeaders"}); # this function should be called once
21442
21443 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021444 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021445 my @Headers = cmd_find($CppDir,"f");
21446 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21447 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021448 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021449 my $FileName = get_filename($Path);
21450 if(not defined $DefaultCppHeader{$FileName})
21451 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021452 $DefaultCppHeader{$FileName} = $Path;
21453 }
21454 }
21455 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021456 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021457}
21458
21459sub parse_libname($$$)
21460{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021461 return "" if(not $_[0]);
21462 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21463 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021464 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021465 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21466}
21467
21468sub parse_libname_I($$$)
21469{
21470 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021471
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021472 if($Target eq "symbian") {
21473 return parse_libname_symbian($Name, $Type);
21474 }
21475 elsif($Target eq "windows") {
21476 return parse_libname_windows($Name, $Type);
21477 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021478
21479 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021480 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021481 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021482 { # libSDL-1.2.so.0.7.1
21483 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021484 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 if($Type eq "name")
21486 { # libSDL-1.2
21487 # libwbxml2
21488 return $2;
21489 }
21490 elsif($Type eq "name+ext")
21491 { # libSDL-1.2.so
21492 # libwbxml2.so
21493 return $1;
21494 }
21495 elsif($Type eq "version")
21496 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021497 if(defined $7
21498 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021499 { # 0.7.1
21500 return $7;
21501 }
21502 else
21503 { # libc-2.5.so (=>2.5 version)
21504 my $MV = $5;
21505 $MV=~s/\A[\-\_]+//g;
21506 return $MV;
21507 }
21508 }
21509 elsif($Type eq "short")
21510 { # libSDL
21511 # libwbxml2
21512 return $3;
21513 }
21514 elsif($Type eq "shortest")
21515 { # SDL
21516 # wbxml
21517 return shortest_name($3);
21518 }
21519 }
21520 return "";# error
21521}
21522
21523sub parse_libname_symbian($$)
21524{
21525 my ($Name, $Type) = @_;
21526 my $Ext = getLIB_EXT("symbian");
21527 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21528 { # libpthread{00010001}.dso
21529 if($Type eq "name")
21530 { # libpthread{00010001}
21531 return $2;
21532 }
21533 elsif($Type eq "name+ext")
21534 { # libpthread{00010001}.dso
21535 return $1;
21536 }
21537 elsif($Type eq "version")
21538 { # 00010001
21539 my $V = $4;
21540 $V=~s/\{(.+)\}/$1/;
21541 return $V;
21542 }
21543 elsif($Type eq "short")
21544 { # libpthread
21545 return $3;
21546 }
21547 elsif($Type eq "shortest")
21548 { # pthread
21549 return shortest_name($3);
21550 }
21551 }
21552 return "";# error
21553}
21554
21555sub parse_libname_windows($$)
21556{
21557 my ($Name, $Type) = @_;
21558 my $Ext = getLIB_EXT("windows");
21559 if($Name=~/((.+?)\.$Ext)\Z/)
21560 { # netapi32.dll
21561 if($Type eq "name")
21562 { # netapi32
21563 return $2;
21564 }
21565 elsif($Type eq "name+ext")
21566 { # netapi32.dll
21567 return $1;
21568 }
21569 elsif($Type eq "version")
21570 { # DLL version embedded
21571 # at binary-level
21572 return "";
21573 }
21574 elsif($Type eq "short")
21575 { # netapi32
21576 return $2;
21577 }
21578 elsif($Type eq "shortest")
21579 { # netapi
21580 return shortest_name($2);
21581 }
21582 }
21583 return "";# error
21584}
21585
21586sub shortest_name($)
21587{
21588 my $Name = $_[0];
21589 # remove prefix
21590 $Name=~s/\A(lib|open)//;
21591 # remove suffix
21592 $Name=~s/[\W\d_]+\Z//i;
21593 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21594 return $Name;
21595}
21596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021597sub createSymbolsList($$$$$)
21598{
21599 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021600
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021601 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021602 prepareSymbols(1);
21603
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021604 my %SymbolHeaderLib = ();
21605 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021607 # Get List
21608 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21609 {
21610 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021611 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021612 next;
21613 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021614 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021615 { # skip other symbols
21616 next;
21617 }
21618 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21619 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021620 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021621 next;
21622 }
21623 my $DyLib = $Symbol_Library{1}{$Symbol};
21624 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021625 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021626 next;
21627 }
21628 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21629 $Total+=1;
21630 }
21631 # Draw List
21632 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21633 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21634 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21635 {
21636 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21637 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021638 my %NS_Symbol = ();
21639 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021640 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021641 }
21642 foreach my $NameSpace (sort keys(%NS_Symbol))
21643 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021644 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021645 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21646 foreach my $Symbol (@SortedInterfaces)
21647 {
21648 my $SubReport = "";
21649 my $Signature = get_Signature($Symbol, 1);
21650 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021651 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021652 }
21653 if($Symbol=~/\A(_Z|\?)/)
21654 {
21655 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021656 $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 +040021657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021658 else {
21659 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21660 }
21661 }
21662 else
21663 {
21664 if($Signature) {
21665 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21666 }
21667 else {
21668 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21669 }
21670 }
21671 $SYMBOLS_LIST .= $SubReport;
21672 }
21673 }
21674 $SYMBOLS_LIST .= "<br/>\n";
21675 }
21676 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021677 # clear info
21678 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21679 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21680 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21681 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021682 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021683 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021684 my $CssStyles = readModule("Styles", "SymbolsList.css");
21685 my $JScripts = readModule("Scripts", "Sections.js");
21686 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021687 my $Title = "$LName: public symbols";
21688 my $Keywords = "$LName, API, symbols";
21689 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021690 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021691 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021692 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021693 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021694 writeFile($SaveTo, $SYMBOLS_LIST);
21695}
21696
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021697sub add_target_libs($)
21698{
21699 foreach (@{$_[0]}) {
21700 $TargetLibs{$_} = 1;
21701 }
21702}
21703
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021704sub is_target_lib($)
21705{
21706 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021707 if(not $LName) {
21708 return 0;
21709 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021710 if($OSgroup eq "windows") {
21711 $LName = lc($LName);
21712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021713 if($TargetLibraryName
21714 and $LName!~/\Q$TargetLibraryName\E/) {
21715 return 0;
21716 }
21717 if(keys(%TargetLibs)
21718 and not $TargetLibs{$LName}
21719 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21720 return 0;
21721 }
21722 return 1;
21723}
21724
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021725sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021726{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021727 my ($H, $V) = @_;
21728 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021729 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021730 if($TargetHeaders{$V}{$H}) {
21731 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021732 }
21733 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021734 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021735}
21736
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021737sub readLibs($)
21738{
21739 my $LibVersion = $_[0];
21740 if($OStarget eq "windows")
21741 { # dumpbin.exe will crash
21742 # without VS Environment
21743 check_win32_env();
21744 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021745 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021746 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021747 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021748}
21749
21750sub dump_sorting($)
21751{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021752 my $Hash = $_[0];
21753 return [] if(not $Hash);
21754 my @Keys = keys(%{$Hash});
21755 return [] if($#Keys<0);
21756 if($Keys[0]=~/\A\d+\Z/)
21757 { # numbers
21758 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021759 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021760 else
21761 { # strings
21762 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021763 }
21764}
21765
21766sub printMsg($$)
21767{
21768 my ($Type, $Msg) = @_;
21769 if($Type!~/\AINFO/) {
21770 $Msg = $Type.": ".$Msg;
21771 }
21772 if($Type!~/_C\Z/) {
21773 $Msg .= "\n";
21774 }
21775 if($Quiet)
21776 { # --quiet option
21777 appendFile($COMMON_LOG_PATH, $Msg);
21778 }
21779 else
21780 {
21781 if($Type eq "ERROR") {
21782 print STDERR $Msg;
21783 }
21784 else {
21785 print $Msg;
21786 }
21787 }
21788}
21789
21790sub exitStatus($$)
21791{
21792 my ($Code, $Msg) = @_;
21793 printMsg("ERROR", $Msg);
21794 exit($ERROR_CODE{$Code});
21795}
21796
21797sub exitReport()
21798{ # the tool has run without any errors
21799 printReport();
21800 if($COMPILE_ERRORS)
21801 { # errors in headers may add false positives/negatives
21802 exit($ERROR_CODE{"Compile_Error"});
21803 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021804 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21805 { # --binary
21806 exit($ERROR_CODE{"Incompatible"});
21807 }
21808 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21809 { # --source
21810 exit($ERROR_CODE{"Incompatible"});
21811 }
21812 elsif($RESULT{"Source"}{"Problems"}
21813 or $RESULT{"Binary"}{"Problems"})
21814 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021815 exit($ERROR_CODE{"Incompatible"});
21816 }
21817 else {
21818 exit($ERROR_CODE{"Compatible"});
21819 }
21820}
21821
21822sub readRules($)
21823{
21824 my $Kind = $_[0];
21825 if(not -f $RULES_PATH{$Kind}) {
21826 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21827 }
21828 my $Content = readFile($RULES_PATH{$Kind});
21829 while(my $Rule = parseTag(\$Content, "rule"))
21830 {
21831 my $RId = parseTag(\$Rule, "id");
21832 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21833 foreach my $Prop (@Properties) {
21834 if(my $Value = parseTag(\$Rule, lc($Prop)))
21835 {
21836 $Value=~s/\n[ ]*//;
21837 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21838 }
21839 }
21840 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21841 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21842 }
21843 else {
21844 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21845 }
21846 }
21847}
21848
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021849sub getReportPath($)
21850{
21851 my $Level = $_[0];
21852 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21853 if($Level eq "Binary")
21854 {
21855 if($BinaryReportPath)
21856 { # --bin-report-path
21857 return $BinaryReportPath;
21858 }
21859 elsif($OutputReportPath)
21860 { # --report-path
21861 return $OutputReportPath;
21862 }
21863 else
21864 { # default
21865 return $Dir."/abi_compat_report.$ReportFormat";
21866 }
21867 }
21868 elsif($Level eq "Source")
21869 {
21870 if($SourceReportPath)
21871 { # --src-report-path
21872 return $SourceReportPath;
21873 }
21874 elsif($OutputReportPath)
21875 { # --report-path
21876 return $OutputReportPath;
21877 }
21878 else
21879 { # default
21880 return $Dir."/src_compat_report.$ReportFormat";
21881 }
21882 }
21883 else
21884 {
21885 if($OutputReportPath)
21886 { # --report-path
21887 return $OutputReportPath;
21888 }
21889 else
21890 { # default
21891 return $Dir."/compat_report.$ReportFormat";
21892 }
21893 }
21894}
21895
21896sub printStatMsg($)
21897{
21898 my $Level = $_[0];
21899 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21900}
21901
21902sub listAffected($)
21903{
21904 my $Level = $_[0];
21905 my $List = "";
21906 foreach (keys(%{$TotalAffected{$Level}}))
21907 {
21908 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21909 { # skip "Low"-severity problems
21910 next;
21911 }
21912 $List .= "$_\n";
21913 }
21914 my $Dir = get_dirname(getReportPath($Level));
21915 if($Level eq "Binary") {
21916 writeFile($Dir."/abi_affected.txt", $List);
21917 }
21918 elsif($Level eq "Source") {
21919 writeFile($Dir."/src_affected.txt", $List);
21920 }
21921}
21922
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021923sub printReport()
21924{
21925 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021926 createReport();
21927 if($JoinReport or $DoubleReport)
21928 {
21929 if($RESULT{"Binary"}{"Problems"}
21930 or $RESULT{"Source"}{"Problems"}) {
21931 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021932 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021933 else {
21934 printMsg("INFO", "result: COMPATIBLE");
21935 }
21936 printStatMsg("Binary");
21937 printStatMsg("Source");
21938 if($ListAffected)
21939 { # --list-affected
21940 listAffected("Binary");
21941 listAffected("Source");
21942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021943 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021944 elsif($BinaryOnly)
21945 {
21946 if($RESULT{"Binary"}{"Problems"}) {
21947 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21948 }
21949 else {
21950 printMsg("INFO", "result: COMPATIBLE");
21951 }
21952 printStatMsg("Binary");
21953 if($ListAffected)
21954 { # --list-affected
21955 listAffected("Binary");
21956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021957 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021958 elsif($SourceOnly)
21959 {
21960 if($RESULT{"Source"}{"Problems"}) {
21961 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21962 }
21963 else {
21964 printMsg("INFO", "result: COMPATIBLE");
21965 }
21966 printStatMsg("Source");
21967 if($ListAffected)
21968 { # --list-affected
21969 listAffected("Source");
21970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021972 if($StdOut)
21973 {
21974 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021975 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021976 printMsg("INFO", "compatibility report has been generated to stdout");
21977 }
21978 else
21979 { # default
21980 printMsg("INFO", "compatibility reports have been generated to stdout");
21981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021983 else
21984 {
21985 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021986 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021987 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21988 }
21989 elsif($DoubleReport)
21990 { # default
21991 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21992 }
21993 elsif($BinaryOnly)
21994 { # --binary
21995 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21996 }
21997 elsif($SourceOnly)
21998 { # --source
21999 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
22000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022001 }
22002}
22003
22004sub check_win32_env()
22005{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022006 if(not $ENV{"VCINSTALLDIR"}
22007 or not $ENV{"INCLUDE"}) {
22008 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022009 }
22010}
22011
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022012sub diffSets($$)
22013{
22014 my ($S1, $S2) = @_;
22015 my @SK1 = keys(%{$S1});
22016 my @SK2 = keys(%{$S2});
22017 if($#SK1!=$#SK2) {
22018 return 1;
22019 }
22020 foreach my $K1 (@SK1)
22021 {
22022 if(not defined $S2->{$K1}) {
22023 return 1;
22024 }
22025 }
22026 return 0;
22027}
22028
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022029sub defaultDumpPath($$)
22030{
22031 my ($N, $V) = @_;
22032 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
22033}
22034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022035sub create_ABI_Dump()
22036{
22037 if(not -e $DumpAPI) {
22038 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
22039 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022040
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022041 if(isDump($DumpAPI)) {
22042 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022043 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022044 else {
22045 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022047
22048 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022049 { # set to default: N
22050 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022051 }
22052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022053 initLogging(1);
22054 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022055
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022056 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022057 if($OutputDumpPath)
22058 { # user defined path
22059 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022060 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022061 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
22062
22063 if(not $Archive and not $StdOut)
22064 { # check archive utilities
22065 if($OSgroup eq "windows")
22066 { # using zip
22067 my $ZipCmd = get_CmdPath("zip");
22068 if(not $ZipCmd) {
22069 exitStatus("Not_Found", "can't find \"zip\"");
22070 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022071 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022072 else
22073 { # using tar and gzip
22074 my $TarCmd = get_CmdPath("tar");
22075 if(not $TarCmd) {
22076 exitStatus("Not_Found", "can't find \"tar\"");
22077 }
22078 my $GzipCmd = get_CmdPath("gzip");
22079 if(not $GzipCmd) {
22080 exitStatus("Not_Found", "can't find \"gzip\"");
22081 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022082 }
22083 }
22084
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022085 if(not $Descriptor{1}{"Dump"})
22086 {
22087 if(not $CheckHeadersOnly) {
22088 readLibs(1);
22089 }
22090 if($CheckHeadersOnly) {
22091 setLanguage(1, "C++");
22092 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022093 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022094 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022095 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022096 if(not $Descriptor{1}{"Dump"})
22097 {
22098 if($Descriptor{1}{"Headers"}) {
22099 readHeaders(1);
22100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022101 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022102 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022103 if(not keys(%{$SymbolInfo{1}}))
22104 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022105 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022106 {
22107 if($CheckHeadersOnly) {
22108 exitStatus("Empty_Set", "the set of public symbols is empty");
22109 }
22110 else {
22111 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22112 }
22113 }
22114 }
22115 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022116 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022117 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22118 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022119 if($ExtraDump)
22120 { # add unmangled names to the ABI dump
22121 my @Names = ();
22122 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22123 {
22124 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22125 push(@Names, $MnglName);
22126 }
22127 }
22128 translateSymbols(@Names, 1);
22129 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22130 {
22131 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22132 {
22133 if(my $Unmangled = $tr_name{$MnglName})
22134 {
22135 if($MnglName ne $Unmangled) {
22136 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22137 }
22138 }
22139 }
22140 }
22141 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022142
22143 my %GccConstants = (); # built-in GCC constants
22144 foreach my $Name (keys(%{$Constants{1}}))
22145 {
22146 if(not defined $Constants{1}{$Name}{"Header"})
22147 {
22148 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22149 delete($Constants{1}{$Name});
22150 }
22151 }
22152
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022153 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022154 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022155 "TypeInfo" => $TypeInfo{1},
22156 "SymbolInfo" => $SymbolInfo{1},
22157 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022158 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022159 "SymbolVersion" => $SymVer{1},
22160 "LibraryVersion" => $Descriptor{1}{"Version"},
22161 "LibraryName" => $TargetLibraryName,
22162 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022163 "SkipTypes" => $SkipTypes{1},
22164 "SkipSymbols" => $SkipSymbols{1},
22165 "SkipNameSpaces" => $SkipNameSpaces{1},
22166 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022167 "Headers" => \%HeadersInfo,
22168 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022169 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022170 "NameSpaces" => $NestedNameSpaces{1},
22171 "Target" => $OStarget,
22172 "Arch" => getArch(1),
22173 "WordSize" => $WORD_SIZE{1},
22174 "GccVersion" => get_dumpversion($GCC_PATH),
22175 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22176 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22177 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022178 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022179 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022180 }
22181 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022182 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022184 if($ExtendedCheck)
22185 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022186 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022188 if($BinaryOnly)
22189 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022190 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022191 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022192 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022193 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022194 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022195 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22196 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022197 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022198
22199 my $ABI_DUMP = "";
22200 if($UseXML)
22201 {
22202 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022203 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022205 else
22206 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022207 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022209 if($StdOut)
22210 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022211 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022212 printMsg("INFO", "ABI dump has been generated to stdout");
22213 return;
22214 }
22215 else
22216 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022217 my ($DDir, $DName) = separate_path($DumpPath);
22218 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022219 if(not $Archive) {
22220 $DPath = $DumpPath;
22221 }
22222
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022223 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022224
22225 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022226 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022227 close(DUMP);
22228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022229 if(not -s $DPath) {
22230 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22231 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022232 if($Archive) {
22233 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022234 }
22235
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022236 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022237 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022238 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022239 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022240 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022241 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022242 # 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 +040022243 }
22244}
22245
22246sub quickEmptyReports()
22247{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022248 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022249 # NOTE: the dump contains the "LibraryVersion" attribute
22250 # if you change the version, then your dump will be different
22251 # OVERCOME: use -v1 and v2 options for comparing dumps
22252 # and don't change version in the XML descriptor (and dumps)
22253 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022254 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22255 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022256 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022257 my $FilePath1 = $Descriptor{1}{"Path"};
22258 my $FilePath2 = $Descriptor{2}{"Path"};
22259
22260 if(not isDump_U($FilePath1)) {
22261 $FilePath1 = unpackDump($FilePath1);
22262 }
22263
22264 if(not isDump_U($FilePath2)) {
22265 $FilePath2 = unpackDump($FilePath2);
22266 }
22267
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022268 if($FilePath1 and $FilePath2)
22269 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022270 my $Line = readLineNum($FilePath1, 0);
22271 if($Line=~/xml/)
22272 { # XML format
22273 # is not supported yet
22274 return;
22275 }
22276
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022277 local $/ = undef;
22278
22279 open(DUMP1, $FilePath1);
22280 my $Content1 = <DUMP1>;
22281 close(DUMP1);
22282
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022283 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022284
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022285 if($FilePath1 eq $FilePath2) {
22286 $Eq = 1;
22287 }
22288
22289 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022290 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022291 open(DUMP2, $FilePath2);
22292 my $Content2 = <DUMP2>;
22293 close(DUMP2);
22294
22295 if($Content1 eq $Content2) {
22296 $Eq = 1;
22297 }
22298
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022299 # clean memory
22300 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022301 }
22302
22303 if($Eq)
22304 {
22305 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022306 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022307 my $ABIdump = eval($Content1);
22308
22309 # clean memory
22310 undef $Content1;
22311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022312 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022313 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 +040022314 }
22315 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022316 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22318 }
22319 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022320 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022321 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22322 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022323 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022324
22325 foreach (keys(%{$Registered_Headers{1}})) {
22326 $TargetHeaders{1}{$_} = 1;
22327 }
22328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022329 read_Libs_DumpInfo($ABIdump, 1);
22330 read_Machine_DumpInfo($ABIdump, 1);
22331 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022332
22333 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22334 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22335
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022336 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22337 {
22338 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22339 {
22340 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22341 next;
22342 }
22343 }
22344
22345 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22346 if($Access ne "private")
22347 {
22348 $CheckedSymbols{"Binary"}{$S} = 1;
22349 $CheckedSymbols{"Source"}{$S} = 1;
22350 }
22351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022353 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22354 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022355
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030022356 if(not defined $Descriptor{1}{"Version"}) {
22357 $Descriptor{1}{"Version"} = "X";
22358 }
22359
22360 if(not defined $Descriptor{2}{"Version"}) {
22361 $Descriptor{2}{"Version"} = "Y";
22362 }
22363
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022364 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22365 {
22366 $UsedDump{1}{"DWARF"} = 1;
22367 $UsedDump{2}{"DWARF"} = 1;
22368
22369 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22370 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22371 }
22372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022373 exitReport();
22374 }
22375 }
22376 }
22377}
22378
22379sub initLogging($)
22380{
22381 my $LibVersion = $_[0];
22382 # create log directory
22383 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22384 if($OutputLogPath{$LibVersion})
22385 { # user-defined by -log-path option
22386 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22387 }
22388 if($LogMode ne "n") {
22389 mkpath($LOG_DIR);
22390 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022391 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022392 if($Debug)
22393 { # debug directory
22394 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022395
22396 if(not $ExtraInfo)
22397 { # enable --extra-info
22398 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022401 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022402}
22403
22404sub writeLog($$)
22405{
22406 my ($LibVersion, $Msg) = @_;
22407 if($LogMode ne "n") {
22408 appendFile($LOG_PATH{$LibVersion}, $Msg);
22409 }
22410}
22411
22412sub resetLogging($)
22413{
22414 my $LibVersion = $_[0];
22415 if($LogMode!~/a|n/)
22416 { # remove old log
22417 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022418 if($Debug) {
22419 rmtree($DEBUG_PATH{$LibVersion});
22420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022421 }
22422}
22423
22424sub printErrorLog($)
22425{
22426 my $LibVersion = $_[0];
22427 if($LogMode ne "n") {
22428 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22429 }
22430}
22431
22432sub isDump($)
22433{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022434 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22435 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022436 return $1;
22437 }
22438 return 0;
22439}
22440
22441sub isDump_U($)
22442{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022443 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022444 return $1;
22445 }
22446 return 0;
22447}
22448
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022449sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022450{
22451 # read input XML descriptors or ABI dumps
22452 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022453 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022454 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022455 if(not -e $Descriptor{1}{"Path"}) {
22456 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022457 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022458
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022459 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022460 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022461 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022462 if(not -e $Descriptor{2}{"Path"}) {
22463 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022464 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022466 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022467
22468 if(not defined $DisableQuickEmptyReport)
22469 {
22470 if(isDump($Descriptor{1}{"Path"})
22471 and isDump($Descriptor{2}{"Path"}))
22472 { # optimization: equal ABI dumps
22473 quickEmptyReports();
22474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022475 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022477 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022478
22479 if(isDump($Descriptor{1}{"Path"})) {
22480 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022481 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022482 else {
22483 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22484 }
22485
22486 if(isDump($Descriptor{2}{"Path"})) {
22487 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22488 }
22489 else {
22490 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022491 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022492
22493 if(not $Descriptor{1}{"Version"})
22494 { # set to default: X
22495 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022496 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022497 }
22498
22499 if(not $Descriptor{2}{"Version"})
22500 { # set to default: Y
22501 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022502 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022503 }
22504
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022505 if(not $UsedDump{1}{"V"}) {
22506 initLogging(1);
22507 }
22508
22509 if(not $UsedDump{2}{"V"}) {
22510 initLogging(2);
22511 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022512
22513 # check input data
22514 if(not $Descriptor{1}{"Headers"}) {
22515 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022516 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022517 if(not $Descriptor{2}{"Headers"}) {
22518 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022519 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022520
22521 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022522 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022523 if(not $Descriptor{1}{"Libs"}) {
22524 exitStatus("Error", "can't find libraries info in descriptor d1");
22525 }
22526 if(not $Descriptor{2}{"Libs"}) {
22527 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022528 }
22529 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022530
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022531 if($UseDumps)
22532 { # --use-dumps
22533 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022534 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22535 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022536
22537 unlink($DumpPath1);
22538 unlink($DumpPath2);
22539
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022540 my $pid = fork();
22541 if($pid)
22542 { # dump on two CPU cores
22543 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22544 if($RelativeDirectory{1}) {
22545 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22546 }
22547 if($OutputLogPath{1}) {
22548 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22549 }
22550 if($CrossGcc) {
22551 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22552 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022553 if($Quiet)
22554 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022555 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022556 @PARAMS = (@PARAMS, "-logging-mode", "a");
22557 }
22558 elsif($LogMode and $LogMode ne "w")
22559 { # "w" is default
22560 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022561 }
22562 if($ExtendedCheck) {
22563 @PARAMS = (@PARAMS, "-extended");
22564 }
22565 if($UserLang) {
22566 @PARAMS = (@PARAMS, "-lang", $UserLang);
22567 }
22568 if($TargetVersion{1}) {
22569 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22570 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022571 if($BinaryOnly) {
22572 @PARAMS = (@PARAMS, "-binary");
22573 }
22574 if($SourceOnly) {
22575 @PARAMS = (@PARAMS, "-source");
22576 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022577 if($SortDump) {
22578 @PARAMS = (@PARAMS, "-sort");
22579 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022580 if($DumpFormat and $DumpFormat ne "perl") {
22581 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22582 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022583 if($CheckHeadersOnly) {
22584 @PARAMS = (@PARAMS, "-headers-only");
22585 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022586 if($Debug)
22587 {
22588 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022589 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022591 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022592 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022593 exit(1);
22594 }
22595 }
22596 else
22597 { # child
22598 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22599 if($RelativeDirectory{2}) {
22600 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22601 }
22602 if($OutputLogPath{2}) {
22603 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22604 }
22605 if($CrossGcc) {
22606 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22607 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022608 if($Quiet)
22609 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022610 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022611 @PARAMS = (@PARAMS, "-logging-mode", "a");
22612 }
22613 elsif($LogMode and $LogMode ne "w")
22614 { # "w" is default
22615 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022616 }
22617 if($ExtendedCheck) {
22618 @PARAMS = (@PARAMS, "-extended");
22619 }
22620 if($UserLang) {
22621 @PARAMS = (@PARAMS, "-lang", $UserLang);
22622 }
22623 if($TargetVersion{2}) {
22624 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022626 if($BinaryOnly) {
22627 @PARAMS = (@PARAMS, "-binary");
22628 }
22629 if($SourceOnly) {
22630 @PARAMS = (@PARAMS, "-source");
22631 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022632 if($SortDump) {
22633 @PARAMS = (@PARAMS, "-sort");
22634 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022635 if($DumpFormat and $DumpFormat ne "perl") {
22636 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22637 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022638 if($CheckHeadersOnly) {
22639 @PARAMS = (@PARAMS, "-headers-only");
22640 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022641 if($Debug)
22642 {
22643 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022644 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022646 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022647 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022648 exit(1);
22649 }
22650 else {
22651 exit(0);
22652 }
22653 }
22654 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022656 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022657 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22658 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022659 if($TargetTitle ne $TargetLibraryName) {
22660 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022661 }
22662 if($ShowRetVal) {
22663 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22664 }
22665 if($CrossGcc) {
22666 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22667 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022668 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22669 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022670 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022671 }
22672 if($ReportFormat and $ReportFormat ne "html")
22673 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022674 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22675 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022676 if($OutputReportPath) {
22677 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22678 }
22679 if($BinaryReportPath) {
22680 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22681 }
22682 if($SourceReportPath) {
22683 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22684 }
22685 if($LoggingPath) {
22686 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22687 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022688 if($CheckHeadersOnly) {
22689 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22690 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022691 if($BinaryOnly) {
22692 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22693 }
22694 if($SourceOnly) {
22695 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022697 if($Debug)
22698 {
22699 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22700 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022702 system("perl", $0, @CMP_PARAMS);
22703 exit($?>>8);
22704 }
22705 if(not $Descriptor{1}{"Dump"}
22706 or not $Descriptor{2}{"Dump"})
22707 { # need GCC toolchain to analyze
22708 # header files and libraries
22709 detect_default_paths("inc|lib|gcc");
22710 }
22711 if(not $Descriptor{1}{"Dump"})
22712 {
22713 if(not $CheckHeadersOnly) {
22714 readLibs(1);
22715 }
22716 if($CheckHeadersOnly) {
22717 setLanguage(1, "C++");
22718 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022719 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022720 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022721 }
22722 if(not $Descriptor{2}{"Dump"})
22723 {
22724 if(not $CheckHeadersOnly) {
22725 readLibs(2);
22726 }
22727 if($CheckHeadersOnly) {
22728 setLanguage(2, "C++");
22729 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022730 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022731 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022732 }
22733 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22734 { # support for old ABI dumps
22735 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022736 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022737 {
22738 $WORD_SIZE{1} = $WORD_SIZE{2};
22739 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22740 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022741 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022742 {
22743 $WORD_SIZE{2} = $WORD_SIZE{1};
22744 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22745 }
22746 }
22747 elsif(not $WORD_SIZE{1}
22748 and not $WORD_SIZE{2})
22749 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022750 $WORD_SIZE{1} = "4";
22751 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022752 }
22753 if($Descriptor{1}{"Dump"})
22754 { # support for old ABI dumps
22755 prepareTypes(1);
22756 }
22757 if($Descriptor{2}{"Dump"})
22758 { # support for old ABI dumps
22759 prepareTypes(2);
22760 }
22761 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22762 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22763 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022764 # process input data
22765 if($Descriptor{1}{"Headers"}
22766 and not $Descriptor{1}{"Dump"}) {
22767 readHeaders(1);
22768 }
22769 if($Descriptor{2}{"Headers"}
22770 and not $Descriptor{2}{"Dump"}) {
22771 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022772 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022773
22774 # clean memory
22775 %SystemHeaders = ();
22776 %mangled_name_gcc = ();
22777
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022778 prepareSymbols(1);
22779 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022780
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022781 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022782 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022783
22784 # Virtual Tables
22785 registerVTable(1);
22786 registerVTable(2);
22787
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022788 if(not checkDump(1, "1.22")
22789 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022790 { # support for old ABI dumps
22791 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22792 {
22793 if($ClassName=~/</)
22794 { # templates
22795 if(not defined $VirtualTable{1}{$ClassName})
22796 { # synchronize
22797 delete($VirtualTable{2}{$ClassName});
22798 }
22799 }
22800 }
22801 }
22802
22803 registerOverriding(1);
22804 registerOverriding(2);
22805
22806 setVirtFuncPositions(1);
22807 setVirtFuncPositions(2);
22808
22809 # Other
22810 addParamNames(1);
22811 addParamNames(2);
22812
22813 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022814}
22815
22816sub compareAPIs($)
22817{
22818 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022819
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022820 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022821 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022822
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022823 if($Level eq "Binary") {
22824 printMsg("INFO", "comparing ABIs ...");
22825 }
22826 else {
22827 printMsg("INFO", "comparing APIs ...");
22828 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022829
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022830 if($CheckHeadersOnly
22831 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022832 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022833 detectAdded_H($Level);
22834 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022835 }
22836 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022837 { # added/removed in libs
22838 detectAdded($Level);
22839 detectRemoved($Level);
22840 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022841
22842 mergeSymbols($Level);
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022843
22844 if(not defined $DisableConstantsCheck)
22845 {
22846 if(keys(%{$CheckedSymbols{$Level}})) {
22847 mergeConstants($Level);
22848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022849 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022850
22851 $Cache{"mergeTypes"} = (); # free memory
22852
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022853 if($CheckHeadersOnly
22854 or $Level eq "Source")
22855 { # added/removed in headers
22856 mergeHeaders($Level);
22857 }
22858 else
22859 { # added/removed in libs
22860 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022861 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022862
22863 foreach my $S (keys(%{$CompatProblems{$Level}}))
22864 {
22865 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22866 {
22867 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22868 {
22869 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22870 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22871 }
22872 }
22873 }
22874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022875}
22876
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022877sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022878{
22879 my %Opts = (
22880 "OStarget"=>$OStarget,
22881 "Debug"=>$Debug,
22882 "Quiet"=>$Quiet,
22883 "LogMode"=>$LogMode,
22884 "CheckHeadersOnly"=>$CheckHeadersOnly,
22885
22886 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022887 "GCC_PATH"=>$GCC_PATH,
22888 "TargetSysInfo"=>$TargetSysInfo,
22889 "CrossPrefix"=>$CrossPrefix,
22890 "TargetLibraryName"=>$TargetLibraryName,
22891 "CrossGcc"=>$CrossGcc,
22892 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022893 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030022894 "CxxIncompat"=>$CxxIncompat,
22895 "SkipUnidentified"=>$SkipUnidentified,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022896 "DisableConstantsCheck"=>$DisableConstantsCheck,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022897
22898 "BinaryOnly" => $BinaryOnly,
22899 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022900 );
22901 return \%Opts;
22902}
22903
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022904sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022905{
22906 my %CODE_ERROR = reverse(%ERROR_CODE);
22907 return $CODE_ERROR{$_[0]};
22908}
22909
22910sub scenario()
22911{
22912 if($StdOut)
22913 { # enable quiet mode
22914 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022915 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022916 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022917 if(not $LogMode)
22918 { # default
22919 $LogMode = "w";
22920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022921 if($UserLang)
22922 { # --lang=C++
22923 $UserLang = uc($UserLang);
22924 $COMMON_LANGUAGE{1}=$UserLang;
22925 $COMMON_LANGUAGE{2}=$UserLang;
22926 }
22927 if($LoggingPath)
22928 {
22929 $OutputLogPath{1} = $LoggingPath;
22930 $OutputLogPath{2} = $LoggingPath;
22931 if($Quiet) {
22932 $COMMON_LOG_PATH = $LoggingPath;
22933 }
22934 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022935
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022936 if($Quick) {
22937 $ADD_TMPL_INSTANCES = 0;
22938 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022939 if($OutputDumpPath)
22940 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022941 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022942 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22943 }
22944 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022945 if($BinaryOnly and $SourceOnly)
22946 { # both --binary and --source
22947 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022948 if(not $CmpSystems)
22949 {
22950 $BinaryOnly = 0;
22951 $SourceOnly = 0;
22952 }
22953
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022954 $DoubleReport = 1;
22955 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022956
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022957 if($OutputReportPath)
22958 { # --report-path
22959 $DoubleReport = 0;
22960 $JoinReport = 1;
22961 }
22962 }
22963 elsif($BinaryOnly or $SourceOnly)
22964 { # --binary or --source
22965 $DoubleReport = 0;
22966 $JoinReport = 0;
22967 }
22968 if($UseXML)
22969 { # --xml option
22970 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022971 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022973 if($ReportFormat)
22974 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022975 $ReportFormat = lc($ReportFormat);
22976 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022977 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022979 if($ReportFormat eq "htm")
22980 { # HTM == HTML
22981 $ReportFormat = "html";
22982 }
22983 elsif($ReportFormat eq "xml")
22984 { # --report-format=XML equal to --xml
22985 $UseXML = 1;
22986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022987 }
22988 else
22989 { # default: HTML
22990 $ReportFormat = "html";
22991 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022992 if($DumpFormat)
22993 { # validate
22994 $DumpFormat = lc($DumpFormat);
22995 if($DumpFormat!~/\A(xml|perl)\Z/) {
22996 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22997 }
22998 if($DumpFormat eq "xml")
22999 { # --dump-format=XML equal to --xml
23000 $UseXML = 1;
23001 }
23002 }
23003 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040023004 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023005 $DumpFormat = "perl";
23006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023007 if($Quiet and $LogMode!~/a|n/)
23008 { # --quiet log
23009 if(-f $COMMON_LOG_PATH) {
23010 unlink($COMMON_LOG_PATH);
23011 }
23012 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040023013 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023014 $CheckUndefined = 1;
23015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023016 if($TestTool and $UseDumps)
23017 { # --test && --use-dumps == --test-dump
23018 $TestDump = 1;
23019 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040023020 if($Tolerant)
23021 { # enable all
23022 $Tolerance = 1234;
23023 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023024 if($Help)
23025 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023026 HELP_MESSAGE();
23027 exit(0);
23028 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030023029 if($InfoMsg)
23030 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023031 INFO_MESSAGE();
23032 exit(0);
23033 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023034 if($ShowVersion)
23035 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023036 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 +040023037 exit(0);
23038 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023039 if($DumpVersion)
23040 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023041 printMsg("INFO", $TOOL_VERSION);
23042 exit(0);
23043 }
23044 if($ExtendedCheck) {
23045 $CheckHeadersOnly = 1;
23046 }
23047 if($SystemRoot_Opt)
23048 { # user defined root
23049 if(not -e $SystemRoot_Opt) {
23050 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
23051 }
23052 $SystemRoot = $SystemRoot_Opt;
23053 $SystemRoot=~s/[\/]+\Z//g;
23054 if($SystemRoot) {
23055 $SystemRoot = get_abs_path($SystemRoot);
23056 }
23057 }
23058 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023059
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023060 if($SortDump)
23061 {
23062 $Data::Dumper::Useperl = 1;
23063 $Data::Dumper::Sortkeys = \&dump_sorting;
23064 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023066 if($TargetLibsPath)
23067 {
23068 if(not -f $TargetLibsPath) {
23069 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
23070 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023071 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
23072 {
23073 if($OSgroup eq "windows") {
23074 $TargetLibs{lc($Lib)} = 1;
23075 }
23076 else {
23077 $TargetLibs{$Lib} = 1;
23078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023079 }
23080 }
23081 if($TargetHeadersPath)
23082 { # --headers-list
23083 if(not -f $TargetHeadersPath) {
23084 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
23085 }
23086 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
23087 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023088 $TargetHeaders{1}{get_filename($Header)} = 1;
23089 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023090 }
23091 }
23092 if($TargetHeader)
23093 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023094 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
23095 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023096 }
23097 if($TestTool
23098 or $TestDump)
23099 { # --test, --test-dump
23100 detect_default_paths("bin|gcc"); # to compile libs
23101 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023102 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030023103 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023104 exit(0);
23105 }
23106 if($DumpSystem)
23107 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023108 if(-d $MODULES_DIR."/Targets/"
23109 and -d $MODULES_DIR."/Targets/".$OStarget) {
23110 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
23111 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023112 if(not $TargetSysInfo) {
23113 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
23114 }
23115
23116 if(not -d $TargetSysInfo) {
23117 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23118 }
23119
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023120 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023121 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023122 { # system XML descriptor
23123 if(not -f $DumpSystem) {
23124 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23125 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023126
23127 my $SDesc = readFile($DumpSystem);
23128 if(my $RelDir = $RelativeDirectory{1}) {
23129 $SDesc =~ s/{RELPATH}/$RelDir/g;
23130 }
23131
23132 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023133 foreach (@{$Ret->{"Tools"}})
23134 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023135 push_U($SystemPaths{"bin"}, $_);
23136 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023137 }
23138 if($Ret->{"CrossPrefix"}) {
23139 $CrossPrefix = $Ret->{"CrossPrefix"};
23140 }
23141 }
23142 elsif($SystemRoot_Opt)
23143 { # -sysroot "/" option
23144 # default target: /usr/lib, /usr/include
23145 # search libs: /usr/lib and /lib
23146 if(not -e $SystemRoot."/usr/lib") {
23147 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23148 }
23149 if(not -e $SystemRoot."/lib") {
23150 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23151 }
23152 if(not -e $SystemRoot."/usr/include") {
23153 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23154 }
23155 readSystemDescriptor("
23156 <name>
23157 $DumpSystem
23158 </name>
23159 <headers>
23160 $SystemRoot/usr/include
23161 </headers>
23162 <libs>
23163 $SystemRoot/usr/lib
23164 </libs>
23165 <search_libs>
23166 $SystemRoot/lib
23167 </search_libs>");
23168 }
23169 else {
23170 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23171 }
23172 detect_default_paths("bin|gcc"); # to check symbols
23173 if($OStarget eq "windows")
23174 { # to run dumpbin.exe
23175 # and undname.exe
23176 check_win32_env();
23177 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023178 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023179 exit(0);
23180 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023181
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023182 if($CmpSystems)
23183 { # --cmp-systems
23184 detect_default_paths("bin"); # to extract dumps
23185 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023186 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023187 exit(0);
23188 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023189
23190 if(not $CountSymbols)
23191 {
23192 if(not $TargetLibraryName) {
23193 exitStatus("Error", "library name is not selected (-l option)");
23194 }
23195 else
23196 { # validate library name
23197 if($TargetLibraryName=~/[\*\/\\]/) {
23198 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023200 }
23201 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023202
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023203 if(not $TargetTitle) {
23204 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023205 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023206
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023207 if($SymbolsListPath)
23208 {
23209 if(not -f $SymbolsListPath) {
23210 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23211 }
23212 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23213 $SymbolsList{$Interface} = 1;
23214 }
23215 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023216 if($TypesListPath)
23217 {
23218 if(not -f $TypesListPath) {
23219 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23220 }
23221 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23222 $TypesList{$Type} = 1;
23223 }
23224 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023225 if($SkipSymbolsListPath)
23226 {
23227 if(not -f $SkipSymbolsListPath) {
23228 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23229 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023230 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23231 {
23232 $SkipSymbols{1}{$Interface} = 1;
23233 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023234 }
23235 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023236 if($SkipTypesListPath)
23237 {
23238 if(not -f $SkipTypesListPath) {
23239 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23240 }
23241 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23242 {
23243 $SkipTypes{1}{$Type} = 1;
23244 $SkipTypes{2}{$Type} = 1;
23245 }
23246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023247 if($SkipHeadersPath)
23248 {
23249 if(not -f $SkipHeadersPath) {
23250 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23251 }
23252 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023253 { # register for both versions
23254 $SkipHeadersList{1}{$Path} = 1;
23255 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023257 my ($CPath, $Type) = classifyPath($Path);
23258 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023259 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023260 }
23261 }
23262 if($ParamNamesPath)
23263 {
23264 if(not -f $ParamNamesPath) {
23265 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23266 }
23267 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23268 {
23269 if($Line=~s/\A(\w+)\;//)
23270 {
23271 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023272 if($Line=~/;(\d+);/)
23273 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023274 while($Line=~s/(\d+);(\w+)//) {
23275 $AddIntParams{$Interface}{$1}=$2;
23276 }
23277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023278 else
23279 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023280 my $Num = 0;
23281 foreach my $Name (split(/;/, $Line)) {
23282 $AddIntParams{$Interface}{$Num++}=$Name;
23283 }
23284 }
23285 }
23286 }
23287 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023289 if($AppPath)
23290 {
23291 if(not -f $AppPath) {
23292 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23293 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023294
23295 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023296 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023297 $SymbolsList_App{$Interface} = 1;
23298 }
23299 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023300
23301 if($CountSymbols)
23302 {
23303 if(not -e $CountSymbols) {
23304 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23305 }
23306
23307 read_ABI_Dump(1, $CountSymbols);
23308
23309 foreach my $Id (keys(%{$SymbolInfo{1}}))
23310 {
23311 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23312 if(not $MnglName) {
23313 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23314 }
23315
23316 if(my $SV = $SymVer{1}{$MnglName}) {
23317 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23318 }
23319 else {
23320 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23321 }
23322
23323 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23324 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23325 }
23326 }
23327
23328 my $Count = 0;
23329 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23330 {
23331 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23332 next;
23333 }
23334 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23335 next;
23336 }
23337 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23338 next;
23339 }
23340
23341 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23342 }
23343
23344 printMsg("INFO", $Count);
23345 exit(0);
23346 }
23347
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023348 if($DumpAPI)
23349 { # --dump-abi
23350 # make an API dump
23351 create_ABI_Dump();
23352 exit($COMPILE_ERRORS);
23353 }
23354 # default: compare APIs
23355 # -d1 <path>
23356 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023357 compareInit();
23358 if($JoinReport or $DoubleReport)
23359 {
23360 compareAPIs("Binary");
23361 compareAPIs("Source");
23362 }
23363 elsif($BinaryOnly) {
23364 compareAPIs("Binary");
23365 }
23366 elsif($SourceOnly) {
23367 compareAPIs("Source");
23368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023369 exitReport();
23370}
23371
23372scenario();