blob: d0bf036a58d2f135c14bc5f7c685bd9f7e10312a [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko959dd192016-10-06 19:51:11 +03003# ABI Compliance Checker (ABICC) 1.99.25
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030022# - Perl 5
23# - Ctags
24# - ABI Dumper >= 0.99.15
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040025#
26# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040027# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030028# - Ctags
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040029#
30# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040031# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040032# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040033# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030034# - Sigcheck v2.52 or newer
35# - GnuWin Zip and UnZip
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030036# - Ctags (Exuberant or Universal)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040037# - Add tool locations to the PATH environment variable
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030038# - Run vcvars64.bat (C:\Microsoft Visual Studio 9.0\VC\bin\)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040039#
40# This program is free software: you can redistribute it and/or modify
41# it under the terms of the GNU General Public License or the GNU Lesser
42# General Public License as published by the Free Software Foundation.
43#
44# This program is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47# GNU General Public License for more details.
48#
49# You should have received a copy of the GNU General Public License
50# and the GNU Lesser General Public License along with this program.
51# If not, see <http://www.gnu.org/licenses/>.
52###########################################################################
53use Getopt::Long;
54Getopt::Long::Configure ("posix_default", "no_ignore_case");
55use File::Path qw(mkpath rmtree);
56use File::Temp qw(tempdir);
57use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040058use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040059use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040060use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040061use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040062
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030063my $TOOL_VERSION = "1.99.25";
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030064my $ABI_DUMP_VERSION = "3.3";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030088$SkipHeadersPath, $CxxCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CxxIncompat,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030093$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030095$DisableQuickEmptyReport, $SkipTypedefUncover, $MinGWCompat, $SkipUnidentified,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030096$DisableConstantsCheck, $SkipAddedConstants, $SkipRemovedConstants, $TestABIDumper);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300149my %HomePage = (
150 "Dev"=>"https://github.com/lvc/abi-compliance-checker",
151 "Wiki"=>"https://lvc.github.io/abi-compliance-checker/"
152);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400154my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400155A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300156Copyright (C) 2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157License: GNU LGPL or GNU GPL
158
159Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400160Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400161
162OLD.xml and NEW.xml are XML-descriptors:
163
164 <version>
165 1.0
166 </version>
167
168 <headers>
169 /path/to/headers/
170 </headers>
171
172 <libs>
173 /path/to/libraries/
174 </libs>
175
176More info: $CmdName --help\n";
177
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400178if($#ARGV==-1)
179{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400180 printMsg("INFO", $ShortUsage);
181 exit(0);
182}
183
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400184GetOptions("h|help!" => \$Help,
185 "i|info!" => \$InfoMsg,
186 "v|version!" => \$ShowVersion,
187 "dumpversion!" => \$DumpVersion,
188# general options
189 "l|lib|library=s" => \$TargetLibraryName,
190 "d1|old|o=s" => \$Descriptor{1}{"Path"},
191 "d2|new|n=s" => \$Descriptor{2}{"Path"},
192 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 "app|application=s" => \$AppPath,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300195 "static|static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400196 "gcc-path|cross-gcc=s" => \$CrossGcc,
197 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
198 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400199 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300200 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
201 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400202 "s|strict!" => \$StrictCompat,
203 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300204 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400205 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300206 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300207 "disable-constants-check!" => \$DisableConstantsCheck,
208 "skip-added-constants!" => \$SkipAddedConstants,
209 "skip-removed-constants!" => \$SkipRemovedConstants,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400210 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400211 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400212 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400214 "show-retval!" => \$ShowRetVal,
215 "use-dumps!" => \$UseDumps,
216 "nostdinc!" => \$NoStdInc,
217 "dump-system=s" => \$DumpSystem,
218 "sysinfo=s" => \$TargetSysInfo,
219 "cmp-systems!" => \$CmpSystems,
220 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "ext|extended!" => \$ExtendedCheck,
222 "q|quiet!" => \$Quiet,
223 "stdout!" => \$StdOut,
224 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400225 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400226 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400228 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400229 "binary|bin|abi!" => \$BinaryOnly,
230 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400231 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300232 "count-symbols=s" => \$CountSymbols,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300233 "old-style!" => \$OldStyle,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234# other options
235 "test!" => \$TestTool,
236 "test-dump!" => \$TestDump,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300237 "test-abi-dumper!" => \$TestABIDumper,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "debug!" => \$Debug,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300239 "cpp-compatible!" => \$CxxCompat,
240 "cxx-incompatible|cpp-incompatible!" => \$CxxIncompat,
241 "mingw-compatible!" => \$MinGWCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "p|params=s" => \$ParamNamesPath,
243 "relpath1|relpath=s" => \$RelativeDirectory{1},
244 "relpath2=s" => \$RelativeDirectory{2},
245 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400246 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400248 "bin-report-path=s" => \$BinaryReportPath,
249 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400250 "log-path=s" => \$LoggingPath,
251 "log1-path=s" => \$OutputLogPath{1},
252 "log2-path=s" => \$OutputLogPath{2},
253 "logging-mode=s" => \$LogMode,
254 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300255 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400256 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400257 "extra-info=s" => \$ExtraInfo,
258 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400259 "force!" => \$Force,
260 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400261 "tolerant!" => \$Tolerant,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300262 "skip-unidentified!" => \$SkipUnidentified,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400263 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400264 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300265 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400266 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300267 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
268 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300269 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300270 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400271) or ERR_MESSAGE();
272
273sub ERR_MESSAGE()
274{
275 printMsg("INFO", "\n".$ShortUsage);
276 exit($ERROR_CODE{"Error"});
277}
278
279my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
280my $SLIB_TYPE = $LIB_TYPE;
281if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
282{ # show as "shared" library
283 $SLIB_TYPE = "shared";
284}
285my $LIB_EXT = getLIB_EXT($OSgroup);
286my $AR_EXT = getAR_EXT($OSgroup);
287my $BYTE_SIZE = 8;
288my $COMMON_LOG_PATH = "logs/run.log";
289
290my $HelpMessage="
291NAME:
292 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400293 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400294
295DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400296 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400297 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
298 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
299 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
300 and/or source-level compatibility: changes in calling stack, v-table changes,
301 removed symbols, renamed fields, etc. Binary incompatibility may result in
302 crashing or incorrect behavior of applications built with an old version of
303 a library if they run on a new one. Source incompatibility may result in
304 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400305
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400306 The tool is intended for developers of software libraries and maintainers
307 of operating systems who are interested in ensuring backward compatibility,
308 i.e. allow old applications to run or to be recompiled with newer library
309 versions.
310
311 Also the tool can be used by ISVs for checking applications portability to
312 new library versions. Found issues can be taken into account when adapting
313 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400314
315 This tool is free software: you can redistribute it and/or modify it
316 under the terms of the GNU LGPL or GNU GPL.
317
318USAGE:
319 $CmdName [options]
320
321EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400322 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400323
324 OLD.xml and NEW.xml are XML-descriptors:
325
326 <version>
327 1.0
328 </version>
329
330 <headers>
331 /path1/to/header(s)/
332 /path2/to/header(s)/
333 ...
334 </headers>
335
336 <libs>
337 /path1/to/library(ies)/
338 /path2/to/library(ies)/
339 ...
340 </libs>
341
342INFORMATION OPTIONS:
343 -h|-help
344 Print this help.
345
346 -i|-info
347 Print complete info.
348
349 -v|-version
350 Print version information.
351
352 -dumpversion
353 Print the tool version ($TOOL_VERSION) and don't do anything else.
354
355GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400356 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400357 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400358
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400359 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400360 Descriptor of 1st (old) library version.
361 It may be one of the following:
362
363 1. XML-descriptor (VERSION.xml file):
364
365 <version>
366 1.0
367 </version>
368
369 <headers>
370 /path1/to/header(s)/
371 /path2/to/header(s)/
372 ...
373 </headers>
374
375 <libs>
376 /path1/to/library(ies)/
377 /path2/to/library(ies)/
378 ...
379 </libs>
380
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300381 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400382
383 2. ABI dump generated by -dump option
384 3. Directory with headers and/or $SLIB_TYPE libraries
385 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400386
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300387 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400388 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400389
390 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400391 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400392
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400393 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400394 Descriptor of 2nd (new) library version.
395
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400396 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400397 Create library ABI dump for the input XML descriptor. You can
398 transfer it anywhere and pass instead of the descriptor. Also
399 it can be used for debugging the tool.
400
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300401 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402
403sub HELP_MESSAGE() {
404 printMsg("INFO", $HelpMessage."
405MORE INFO:
406 $CmdName --info\n");
407}
408
409sub INFO_MESSAGE()
410{
411 printMsg("INFO", "$HelpMessage
412EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400413 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300414 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415 for portability to the new library version.
416
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300417 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418 Check static libraries instead of the shared ones. The <libs> section
419 of the XML-descriptor should point to static libraries location.
420
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300421 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422 Path to the cross GCC compiler to use instead of the usual (host) GCC.
423
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300424 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400425 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300426
427 -gcc-options OPTS
428 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400430 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400431 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400432 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400434 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200436 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437
438 In general case you should specify it in the XML-descriptor:
439 <version>
440 VERSION
441 </version>
442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 Specify 2nd library version outside the descriptor.
445
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400446 -vnum NUM
447 Specify the library version in the generated ABI dump. The <version> section
448 of the input XML descriptor will be overwritten in this case.
449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 -s|-strict
451 Treat all compatibility warnings as problems. Add a number of \"Low\"
452 severity problems to the return value of the tool.
453
454 -headers-only
455 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
456 provide a low quality compatibility report with false positives and
457 without detecting of added/removed symbols.
458
459 Alternatively you can write \"none\" word to the <libs> section
460 in the XML-descriptor:
461 <libs>
462 none
463 </libs>
464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400465 -show-retval
466 Show the symbol's return type in the report.
467
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400468 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300469 This option allows to specify a file with a list of symbols (mangled
470 names in C++) that should be checked. Other symbols will not be checked.
471
472 -types-list PATH
473 This option allows to specify a file with a list of types that should
474 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400475
476 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300477 The list of symbols that should not be checked.
478
479 -skip-types PATH
480 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400481
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300482 -disable-constants-check
483 Do not check for changes in constants.
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300484
485 -skip-added-constants
486 Do not detect added constants.
487
488 -skip-removed-constants
489 Do not detect removed constants.
490
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400491 -headers-list PATH
492 The file with a list of headers, that should be checked/dumped.
493
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400494 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496
497 -header NAME
498 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
500 -use-dumps
501 Make dumps for two versions of a library and compare dumps. This should
502 increase the performance of the tool and decrease the system memory usage.
503
504 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400505 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400507 -dump-system NAME -sysroot DIR
508 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400509 create XML descriptors and make ABI dumps for each library. The result
510 set of ABI dumps can be compared (--cmp-systems) with the other one
511 created for other version of operating system in order to check them for
512 compatibility. Do not forget to specify -cross-gcc option if your target
513 system requires some specific version of GCC compiler (different from
514 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400515 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400516
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400517 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518 The same as the previous option but takes an XML descriptor of the target
519 system as input, where you should describe it:
520
521 /* Primary sections */
522
523 <name>
524 /* Name of the system */
525 </name>
526
527 <headers>
528 /* The list of paths to header files and/or
529 directories with header files, one per line */
530 </headers>
531
532 <libs>
533 /* The list of paths to shared libraries and/or
534 directories with shared libraries, one per line */
535 </libs>
536
537 /* Optional sections */
538
539 <search_headers>
540 /* List of directories to be searched
541 for header files to automatically
542 generate include paths, one per line */
543 </search_headers>
544
545 <search_libs>
546 /* List of directories to be searched
547 for shared libraries to resolve
548 dependencies, one per line */
549 </search_libs>
550
551 <tools>
552 /* List of directories with tools used
553 for analysis (GCC toolchain), one per line */
554 </tools>
555
556 <cross_prefix>
557 /* GCC toolchain prefix.
558 Examples:
559 arm-linux-gnueabi
560 arm-none-symbianelf */
561 </cross_prefix>
562
563 <gcc_options>
564 /* Additional GCC options, one per line */
565 </gcc_options>
566
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400567 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300568 This option should be used with -dump-system option to dump
569 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400570
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400571 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300572 Compare two ABI dumps of a system. Create compatibility reports for
573 each system library and the common HTML report including the summary
574 of test results for all checked libraries.
575
576 Summary report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400577 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400578
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400579 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580 The file with a list of libraries, that should be dumped by
581 the -dump-system option or should be checked by the -cmp-systems option.
582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 -ext|-extended
584 If your library A is supposed to be used by other library B and you
585 want to control the ABI of B, then you should enable this option. The
586 tool will check for changes in all data types, even if they are not
587 used by any function in the library A. Such data types are not part
588 of the A library ABI, but may be a part of the ABI of the B library.
589
590 The short scheme is:
591 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
592
593 -q|-quiet
594 Print all messages to the file instead of stdout and stderr.
595 Default path (can be changed by -log-path option):
596 $COMMON_LOG_PATH
597
598 -stdout
599 Print analysis results (compatibility reports and ABI dumps) to stdout
600 instead of creating a file. This would allow piping data to other programs.
601
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400602 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400603 Change format of compatibility report.
604 Formats:
605 htm - HTML format (default)
606 xml - XML format
607
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400608 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400609 Change format of ABI dump.
610 Formats:
611 perl - Data::Dumper format (default)
612 xml - XML format
613
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400614 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400615 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400618 Set library language (C or C++). You can use this option if the tool
619 cannot auto-detect a language. This option may be useful for checking
620 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400621
622 -arch ARCH
623 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
624 ect.). The option is useful if the tool cannot detect correct architecture
625 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400627 -binary|-bin|-abi
628 Show \"Binary\" compatibility problems only.
629 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400630 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631
632 -source|-src|-api
633 Show \"Source\" compatibility problems only.
634 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400636
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400637 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400638 The maximum number of affected symbols listed under the description
639 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300640
641 -count-symbols PATH
642 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300643
644 -old-style
645 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400647OTHER OPTIONS:
648 -test
649 Run internal tests. Create two binary incompatible versions of a sample
650 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300651 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652
653 -test-dump
654 Test ability to create, read and compare ABI dumps.
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300655
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300656 -test-abi-dumper
657 Compare ABI dumps created by the ABI Dumper tool.
658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 -debug
660 Debugging mode. Print debug info on the screen. Save intermediate
661 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663
Andrey Ponomarenko959dd192016-10-06 19:51:11 +0300664 Also consider using -dump option for debugging the tool.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666 -cpp-compatible
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300667 Do nothing.
668
669 -cxx-incompatible
670 Set this option if input C header files use C++ keywords. The tool
671 will try to replace such keywords at preprocessor stage and replace
672 them back in the final TU dump.
673
674 -mingw-compatible
675 If input header files are compatible with the MinGW GCC compiler,
Andrey Ponomarenkodd172162016-10-04 19:41:25 +0300676 then you can tell the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 Path to file with the function parameter names. It can be used
680 for improving report view if the library header files have no
681 parameter names. File format:
682
683 func1;param1;param2;param3 ...
684 func2;param1;param2;param3 ...
685 ...
686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -relpath PATH
688 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 for dumping the library ABI (see -dump option).
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -relpath1 PATH
692 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -relpath2 PATH
695 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400698 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400702 -sort
703 Enable sorting of data in ABI dumps.
704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400706 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400711 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400716 Path to \"Source\" compatibility report.
717 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 Log path for all messages.
722 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726 Log path for 1st version of a library.
727 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400731 Log path for 2nd version of a library.
732 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400733 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400734
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400736 Change logging mode.
737 Modes:
738 w - overwrite old logs (default)
739 a - append old logs
740 n - do not write any logs
741
742 -list-affected
743 Generate file with the list of incompatible
744 symbols beside the HTML compatibility report.
745 Use 'c++filt \@file' command from GNU binutils
746 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400747 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400749 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400750
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752 The component name in the title and summary of the HTML report.
753 Default:
754 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300755
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300756 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400757 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400758 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759
760 -extra-info DIR
761 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400762
763 -extra-dump
764 Create extended ABI dump containing all symbols
765 from the translation unit.
766
767 -force
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300768 Try to enable this option if the tool checked zero
769 types and symbols in header files.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400770
771 -tolerance LEVEL
772 Apply a set of heuristics to successfully compile input
773 header files. You can enable several tolerance levels by
774 joining them into one string (e.g. 13, 124, etc.).
775 Levels:
776 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
777 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900778 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400779 4 - skip headers included by others
780
781 -tolerant
782 Enable highest tolerance level [1234].
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300783
784 -skip-unidentified
785 Skip header files in 'headers' and 'include_preamble' sections
786 of the XML descriptor that cannot be found. This is useful if
787 you are trying to use the same descriptor for different targets.
788
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400789 -check
790 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400791
792 -quick
793 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300794
795 -disable-quick-empty-report
796 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400797
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300798 -skip-internal-symbols PATTERN
799 Do not check symbols matched by the pattern.
800
801 -skip-internal-types PATTERN
802 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300803
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300804 -skip-typedef-uncover
805 Do not report a problem if type is covered or
806 uncovered by typedef (useful for broken debug info).
807
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300808 -check-private-abi
809 Check data types from the private part of the ABI when
810 comparing ABI dumps created by the ABI Dumper tool with
811 use of the -public-headers option.
812
813 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400815REPORT:
816 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400817 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400818
819 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400820 logs/LIB_NAME/V1/log.txt
821 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400822
823EXIT CODES:
824 0 - Compatible. The tool has run without any errors.
825 non-zero - Incompatible or the tool has run with errors.
826
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400827MORE INFORMATION:
Andrey Ponomarenko26742a82016-09-27 18:27:08 +0300828 ".$HomePage{"Wiki"}."
Andrey Ponomarenko868b1352016-09-29 14:13:30 +0300829 ".$HomePage{"Dev"}."\n\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400830}
831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400832my %Operator_Indication = (
833 "not" => "~",
834 "assign" => "=",
835 "andassign" => "&=",
836 "orassign" => "|=",
837 "xorassign" => "^=",
838 "or" => "|",
839 "xor" => "^",
840 "addr" => "&",
841 "and" => "&",
842 "lnot" => "!",
843 "eq" => "==",
844 "ne" => "!=",
845 "lt" => "<",
846 "lshift" => "<<",
847 "lshiftassign" => "<<=",
848 "rshiftassign" => ">>=",
849 "call" => "()",
850 "mod" => "%",
851 "modassign" => "%=",
852 "subs" => "[]",
853 "land" => "&&",
854 "lor" => "||",
855 "rshift" => ">>",
856 "ref" => "->",
857 "le" => "<=",
858 "deref" => "*",
859 "mult" => "*",
860 "preinc" => "++",
861 "delete" => " delete",
862 "vecnew" => " new[]",
863 "vecdelete" => " delete[]",
864 "predec" => "--",
865 "postinc" => "++",
866 "postdec" => "--",
867 "plusassign" => "+=",
868 "plus" => "+",
869 "minus" => "-",
870 "minusassign" => "-=",
871 "gt" => ">",
872 "ge" => ">=",
873 "new" => " new",
874 "multassign" => "*=",
875 "divassign" => "/=",
876 "div" => "/",
877 "neg" => "-",
878 "pos" => "+",
879 "memref" => "->*",
880 "compound" => "," );
881
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400882my %UnknownOperator;
883
884my %NodeType= (
885 "array_type" => "Array",
886 "binfo" => "Other",
887 "boolean_type" => "Intrinsic",
888 "complex_type" => "Intrinsic",
889 "const_decl" => "Other",
890 "enumeral_type" => "Enum",
891 "field_decl" => "Other",
892 "function_decl" => "Other",
893 "function_type" => "FunctionType",
894 "identifier_node" => "Other",
895 "integer_cst" => "Other",
896 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400897 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400898 "method_type" => "MethodType",
899 "namespace_decl" => "Other",
900 "parm_decl" => "Other",
901 "pointer_type" => "Pointer",
902 "real_cst" => "Other",
903 "real_type" => "Intrinsic",
904 "record_type" => "Struct",
905 "reference_type" => "Ref",
906 "string_cst" => "Other",
907 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400908 "template_type_parm" => "TemplateParam",
909 "typename_type" => "TypeName",
910 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400911 "tree_list" => "Other",
912 "tree_vec" => "Other",
913 "type_decl" => "Other",
914 "union_type" => "Union",
915 "var_decl" => "Other",
916 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400917 "nop_expr" => "Other", #
918 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400919 "offset_type" => "Other" );
920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400921my %CppKeywords_C = map {$_=>1} (
922 # C++ 2003 keywords
923 "public",
924 "protected",
925 "private",
926 "default",
927 "template",
928 "new",
929 #"asm",
930 "dynamic_cast",
931 "auto",
932 "try",
933 "namespace",
934 "typename",
935 "using",
936 "reinterpret_cast",
937 "friend",
938 "class",
939 "virtual",
940 "const_cast",
941 "mutable",
942 "static_cast",
943 "export",
944 # C++0x keywords
945 "noexcept",
946 "nullptr",
947 "constexpr",
948 "static_assert",
949 "explicit",
950 # cannot be used as a macro name
951 # as it is an operator in C++
952 "and",
953 #"and_eq",
954 "not",
955 #"not_eq",
956 "or"
957 #"or_eq",
958 #"bitand",
959 #"bitor",
960 #"xor",
961 #"xor_eq",
962 #"compl"
963);
964
965my %CppKeywords_F = map {$_=>1} (
966 "delete",
967 "catch",
968 "alignof",
969 "thread_local",
970 "decltype",
971 "typeid"
972);
973
974my %CppKeywords_O = map {$_=>1} (
975 "bool",
976 "register",
977 "inline",
978 "operator"
979);
980
981my %CppKeywords_A = map {$_=>1} (
982 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400983 "throw",
984 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400985);
986
987foreach (keys(%CppKeywords_C),
988keys(%CppKeywords_F),
989keys(%CppKeywords_O)) {
990 $CppKeywords_A{$_}=1;
991}
992
993# Header file extensions as described by gcc
994my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
995
996my %IntrinsicMangling = (
997 "void" => "v",
998 "bool" => "b",
999 "wchar_t" => "w",
1000 "char" => "c",
1001 "signed char" => "a",
1002 "unsigned char" => "h",
1003 "short" => "s",
1004 "unsigned short" => "t",
1005 "int" => "i",
1006 "unsigned int" => "j",
1007 "long" => "l",
1008 "unsigned long" => "m",
1009 "long long" => "x",
1010 "__int64" => "x",
1011 "unsigned long long" => "y",
1012 "__int128" => "n",
1013 "unsigned __int128" => "o",
1014 "float" => "f",
1015 "double" => "d",
1016 "long double" => "e",
1017 "__float80" => "e",
1018 "__float128" => "g",
1019 "..." => "z"
1020);
1021
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001022my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001024my %StdcxxMangling = (
1025 "3std"=>"St",
1026 "3std9allocator"=>"Sa",
1027 "3std12basic_string"=>"Sb",
1028 "3std12basic_stringIcE"=>"Ss",
1029 "3std13basic_istreamIcE"=>"Si",
1030 "3std13basic_ostreamIcE"=>"So",
1031 "3std14basic_iostreamIcE"=>"Sd"
1032);
1033
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001034my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001035my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1036
1037my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001038my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001040my %ConstantSuffix = (
1041 "unsigned int"=>"u",
1042 "long"=>"l",
1043 "unsigned long"=>"ul",
1044 "long long"=>"ll",
1045 "unsigned long long"=>"ull"
1046);
1047
1048my %ConstantSuffixR =
1049reverse(%ConstantSuffix);
1050
1051my %OperatorMangling = (
1052 "~" => "co",
1053 "=" => "aS",
1054 "|" => "or",
1055 "^" => "eo",
1056 "&" => "an",#ad (addr)
1057 "==" => "eq",
1058 "!" => "nt",
1059 "!=" => "ne",
1060 "<" => "lt",
1061 "<=" => "le",
1062 "<<" => "ls",
1063 "<<=" => "lS",
1064 ">" => "gt",
1065 ">=" => "ge",
1066 ">>" => "rs",
1067 ">>=" => "rS",
1068 "()" => "cl",
1069 "%" => "rm",
1070 "[]" => "ix",
1071 "&&" => "aa",
1072 "||" => "oo",
1073 "*" => "ml",#de (deref)
1074 "++" => "pp",#
1075 "--" => "mm",#
1076 "new" => "nw",
1077 "delete" => "dl",
1078 "new[]" => "na",
1079 "delete[]" => "da",
1080 "+=" => "pL",
1081 "+" => "pl",#ps (pos)
1082 "-" => "mi",#ng (neg)
1083 "-=" => "mI",
1084 "*=" => "mL",
1085 "/=" => "dV",
1086 "&=" => "aN",
1087 "|=" => "oR",
1088 "%=" => "rM",
1089 "^=" => "eO",
1090 "/" => "dv",
1091 "->*" => "pm",
1092 "->" => "pt",#rf (ref)
1093 "," => "cm",
1094 "?" => "qu",
1095 "." => "dt",
1096 "sizeof"=> "sz"#st
1097);
1098
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001099my %Intrinsic_Keywords = map {$_=>1} (
1100 "true",
1101 "false",
1102 "_Bool",
1103 "_Complex",
1104 "const",
1105 "int",
1106 "long",
1107 "void",
1108 "short",
1109 "float",
1110 "volatile",
1111 "restrict",
1112 "unsigned",
1113 "signed",
1114 "char",
1115 "double",
1116 "class",
1117 "struct",
1118 "union",
1119 "enum"
1120);
1121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001122my %GlibcHeader = map {$_=>1} (
1123 "aliases.h",
1124 "argp.h",
1125 "argz.h",
1126 "assert.h",
1127 "cpio.h",
1128 "ctype.h",
1129 "dirent.h",
1130 "envz.h",
1131 "errno.h",
1132 "error.h",
1133 "execinfo.h",
1134 "fcntl.h",
1135 "fstab.h",
1136 "ftw.h",
1137 "glob.h",
1138 "grp.h",
1139 "iconv.h",
1140 "ifaddrs.h",
1141 "inttypes.h",
1142 "langinfo.h",
1143 "limits.h",
1144 "link.h",
1145 "locale.h",
1146 "malloc.h",
1147 "math.h",
1148 "mntent.h",
1149 "monetary.h",
1150 "nl_types.h",
1151 "obstack.h",
1152 "printf.h",
1153 "pwd.h",
1154 "regex.h",
1155 "sched.h",
1156 "search.h",
1157 "setjmp.h",
1158 "shadow.h",
1159 "signal.h",
1160 "spawn.h",
1161 "stdarg.h",
1162 "stdint.h",
1163 "stdio.h",
1164 "stdlib.h",
1165 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001166 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001167 "tar.h",
1168 "termios.h",
1169 "time.h",
1170 "ulimit.h",
1171 "unistd.h",
1172 "utime.h",
1173 "wchar.h",
1174 "wctype.h",
1175 "wordexp.h" );
1176
1177my %GlibcDir = map {$_=>1} (
1178 "arpa",
1179 "bits",
1180 "gnu",
1181 "netinet",
1182 "net",
1183 "nfs",
1184 "rpc",
1185 "sys",
1186 "linux" );
1187
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001188my %WinHeaders = map {$_=>1} (
1189 "dos.h",
1190 "process.h",
1191 "winsock.h",
1192 "config-win.h",
1193 "mem.h",
1194 "windows.h",
1195 "winsock2.h",
1196 "crtdbg.h",
1197 "ws2tcpip.h"
1198);
1199
1200my %ObsoleteHeaders = map {$_=>1} (
1201 "iostream.h",
1202 "fstream.h"
1203);
1204
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001205my %AlienHeaders = map {$_=>1} (
1206 # Solaris
1207 "thread.h",
1208 "sys/atomic.h",
1209 # HPUX
1210 "sys/stream.h",
1211 # Symbian
1212 "AknDoc.h",
1213 # Atari ST
1214 "ext.h",
1215 "tos.h",
1216 # MS-DOS
1217 "alloc.h",
1218 # Sparc
1219 "sys/atomic.h"
1220);
1221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001222my %ConfHeaders = map {$_=>1} (
1223 "atomic",
1224 "conf.h",
1225 "config.h",
1226 "configure.h",
1227 "build.h",
1228 "setup.h"
1229);
1230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001231my %LocalIncludes = map {$_=>1} (
1232 "/usr/local/include",
1233 "/usr/local" );
1234
1235my %OS_AddPath=(
1236# These paths are needed if the tool cannot detect them automatically
1237 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001238 "include"=>[
1239 "/Library",
1240 "/Developer/usr/include"
1241 ],
1242 "lib"=>[
1243 "/Library",
1244 "/Developer/usr/lib"
1245 ],
1246 "bin"=>[
1247 "/Developer/usr/bin"
1248 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001249 },
1250 "beos"=>{
1251 # Haiku has GCC 2.95.3 by default
1252 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001253 "include"=>[
1254 "/boot/common",
1255 "/boot/develop"
1256 ],
1257 "lib"=>[
1258 "/boot/common/lib",
1259 "/boot/system/lib",
1260 "/boot/apps"
1261 ],
1262 "bin"=>[
1263 "/boot/common/bin",
1264 "/boot/system/bin",
1265 "/boot/develop/abi"
1266 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001268);
1269
1270my %Slash_Type=(
1271 "default"=>"/",
1272 "windows"=>"\\"
1273);
1274
1275my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1276
1277# Global Variables
1278my %COMMON_LANGUAGE=(
1279 1 => "C",
1280 2 => "C" );
1281
1282my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001283my $MAX_CPPFILT_FILE_SIZE = 50000;
1284my $CPPFILT_SUPPORT_FILE;
1285
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +03001286my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION, %CLANG_VERSION);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001288my $STDCXX_TESTING = 0;
1289my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001290my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001291
1292my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001293my $CheckUndefined = 0;
1294
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001295my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001296if($TargetComponent_Opt) {
1297 $TargetComponent = lc($TargetComponent_Opt);
1298}
1299else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300{ # default: library
1301 # other components: header, system, ...
1302 $TargetComponent = "library";
1303}
1304
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001305my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307my $SystemRoot;
1308
1309my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001310my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001311my %LOG_PATH;
1312my %DEBUG_PATH;
1313my %Cache;
1314my %LibInfo;
1315my $COMPILE_ERRORS = 0;
1316my %CompilerOptions;
1317my %CheckedDyLib;
1318my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1319
1320# Constants (#defines)
1321my %Constants;
1322my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001323my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001325# Extra Info
1326my %SymbolHeader;
1327my %KnownLibs;
1328
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001329# Templates
1330my %TemplateInstance;
1331my %BasicTemplate;
1332my %TemplateArg;
1333my %TemplateDecl;
1334my %TemplateMap;
1335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336# Types
1337my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001338my %SkipTypes = (
1339 "1"=>{},
1340 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341my %CheckedTypes;
1342my %TName_Tid;
1343my %EnumMembName_Id;
1344my %NestedNameSpaces = (
1345 "1"=>{},
1346 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001348my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349my %ClassVTable;
1350my %ClassVTable_Content;
1351my %VTableClass;
1352my %AllocableClass;
1353my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001354my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %Class_SubClasses;
1356my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001357my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001358my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001360my %CheckedTypeInfo;
1361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362# Typedefs
1363my %Typedef_BaseName;
1364my %Typedef_Tr;
1365my %Typedef_Eq;
1366my %StdCxxTypedef;
1367my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001368my %MissedBase;
1369my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001370my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371
1372# Symbols
1373my %SymbolInfo;
1374my %tr_name;
1375my %mangled_name_gcc;
1376my %mangled_name;
1377my %SkipSymbols = (
1378 "1"=>{},
1379 "2"=>{} );
1380my %SkipNameSpaces = (
1381 "1"=>{},
1382 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001383my %AddNameSpaces = (
1384 "1"=>{},
1385 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001387my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001388my %SymbolsList_App;
1389my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001390my %Symbol_Library = (
1391 "1"=>{},
1392 "2"=>{} );
1393my %Library_Symbol = (
1394 "1"=>{},
1395 "2"=>{} );
1396my %DepSymbol_Library = (
1397 "1"=>{},
1398 "2"=>{} );
1399my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400 "1"=>{},
1401 "2"=>{} );
1402my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001403my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001405my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001406my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001407my %Library_Needed= (
1408 "1"=>{},
1409 "2"=>{} );
Andrey Ponomarenko991da682016-09-07 19:09:50 +03001410my $DisabledMSVCUnmangling = undef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001412# Extra Info
1413my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001414my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001417my %Include_Preamble = (
1418 "1"=>[],
1419 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001420my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001421my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422my %HeaderName_Paths;
1423my %Header_Dependency;
1424my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001425my %Include_Paths = (
1426 "1"=>[],
1427 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428my %INC_PATH_AUTODETECT = (
1429 "1"=>1,
1430 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001431my %Add_Include_Paths = (
1432 "1"=>[],
1433 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434my %Skip_Include_Paths;
1435my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001436my %Header_ErrorRedirect;
1437my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001438my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001439my %Header_ShouldNotBeUsed;
1440my %RecursiveIncludes;
1441my %Header_Include_Prefix;
1442my %SkipHeaders;
1443my %SkipHeadersList=(
1444 "1"=>{},
1445 "2"=>{} );
1446my %SkipLibs;
1447my %Include_Order;
1448my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001449my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001450my %TUnit_Funcs;
1451my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001453my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454 "1"=>0,
1455 "2"=>0 );
1456my %AutoPreambleMode = (
1457 "1"=>0,
1458 "2"=>0 );
1459my %MinGWMode = (
1460 "1"=>0,
1461 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001462my %Cpp0xMode = (
1463 "1"=>0,
1464 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001465
1466# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001467my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001468my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001469my %RegisteredSONAMEs;
1470my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001472my %CheckedArch;
1473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001474# System Objects
1475my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001476my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001477my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478
1479# System Headers
1480my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001481my @DefaultCppPaths;
1482my @DefaultGccPaths;
1483my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my %DefaultCppHeader;
1485my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001486my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487
1488# Merging
1489my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001490my $Version;
1491my %AddedInt;
1492my %RemovedInt;
1493my %AddedInt_Virt;
1494my %RemovedInt_Virt;
1495my %VirtualReplacement;
1496my %ChangedTypedef;
1497my %CompatRules;
1498my %IncompleteRules;
1499my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001500my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001501my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502my %ReturnedClass;
1503my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001504my %SourceAlternative;
1505my %SourceAlternative_B;
1506my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001507my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001509#Report
1510my %TypeChanges;
1511
1512#Speedup
1513my %TypeProblemsIndex;
1514
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001515# Calling Conventions
1516my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001517 1=>{ "R"=>0, "P"=>0 },
1518 2=>{ "R"=>0, "P"=>0 }
1519);
1520
1521# ABI Dump
1522my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001523
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001524# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my %TargetLibs;
1526my %TargetHeaders;
1527
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001528# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001529my $OStarget = $OSgroup;
1530my %TargetTools;
1531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001532# Recursion locks
1533my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001535my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536my @RecurInclude;
1537my @RecurConstant;
1538
1539# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001540my %SystemPaths = (
1541 "include"=>[],
1542 "lib"=>[],
1543 "bin"=>[]
1544);
1545my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001546my $GCC_PATH;
1547
1548# Symbols versioning
1549my %SymVer = (
1550 "1"=>{},
1551 "2"=>{} );
1552
1553# Problem descriptions
1554my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001555my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556my %TotalAffected;
1557
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001558# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559my $ContentID = 1;
1560my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001561my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1562my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001563my $ContentSpanEnd = "</span>\n";
1564my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1565my $ContentDivEnd = "</div>\n";
1566my $Content_Counter = 0;
1567
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001568# Modes
1569my $JoinReport = 1;
1570my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001571
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001572my %Severity_Val=(
1573 "High"=>3,
1574 "Medium"=>2,
1575 "Low"=>1,
1576 "Safe"=>-1
1577);
1578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579sub get_Modules()
1580{
1581 my $TOOL_DIR = get_dirname($0);
1582 if(not $TOOL_DIR)
1583 { # patch for MS Windows
1584 $TOOL_DIR = ".";
1585 }
1586 my @SEARCH_DIRS = (
1587 # tool's directory
1588 abs_path($TOOL_DIR),
1589 # relative path to modules
1590 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001591 # install path
1592 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001593 );
1594 foreach my $DIR (@SEARCH_DIRS)
1595 {
1596 if(not is_abs($DIR))
1597 { # relative path
1598 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1599 }
1600 if(-d $DIR."/modules") {
1601 return $DIR."/modules";
1602 }
1603 }
1604 exitStatus("Module_Error", "can't find modules");
1605}
1606
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001607my %LoadedModules = ();
1608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001609sub loadModule($)
1610{
1611 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001612 if(defined $LoadedModules{$Name}) {
1613 return;
1614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001615 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1616 if(not -f $Path) {
1617 exitStatus("Module_Error", "can't access \'$Path\'");
1618 }
1619 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001620 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621}
1622
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001623sub readModule($$)
1624{
1625 my ($Module, $Name) = @_;
1626 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1627 if(not -f $Path) {
1628 exitStatus("Module_Error", "can't access \'$Path\'");
1629 }
1630 return readFile($Path);
1631}
1632
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001633sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001634{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001635 my $Number = $_[0];
1636 if(not $Number) {
1637 $Number = 1;
1638 }
1639 else {
1640 $Number = int($Number)+1;
1641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001642 if($Number>3) {
1643 return $Number."th";
1644 }
1645 elsif($Number==1) {
1646 return "1st";
1647 }
1648 elsif($Number==2) {
1649 return "2nd";
1650 }
1651 elsif($Number==3) {
1652 return "3rd";
1653 }
1654 else {
1655 return $Number;
1656 }
1657}
1658
1659sub search_Tools($)
1660{
1661 my $Name = $_[0];
1662 return "" if(not $Name);
1663 if(my @Paths = keys(%TargetTools))
1664 {
1665 foreach my $Path (@Paths)
1666 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001667 if(-f join_P($Path, $Name)) {
1668 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001669 }
1670 if($CrossPrefix)
1671 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001672 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001673 if(-f $Candidate) {
1674 return $Candidate;
1675 }
1676 }
1677 }
1678 }
1679 else {
1680 return "";
1681 }
1682}
1683
1684sub synch_Cmd($)
1685{
1686 my $Name = $_[0];
1687 if(not $GCC_PATH)
1688 { # GCC was not found yet
1689 return "";
1690 }
1691 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001692 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001693 return $Candidate;
1694 }
1695 return "";
1696}
1697
1698sub get_CmdPath($)
1699{
1700 my $Name = $_[0];
1701 return "" if(not $Name);
1702 if(defined $Cache{"get_CmdPath"}{$Name}) {
1703 return $Cache{"get_CmdPath"}{$Name};
1704 }
1705 my %BinUtils = map {$_=>1} (
1706 "c++filt",
1707 "objdump",
1708 "readelf"
1709 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001710 if($BinUtils{$Name} and $GCC_PATH)
1711 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 if(my $Dir = get_dirname($GCC_PATH)) {
1713 $TargetTools{$Dir}=1;
1714 }
1715 }
1716 my $Path = search_Tools($Name);
1717 if(not $Path and $OSgroup eq "windows") {
1718 $Path = search_Tools($Name.".exe");
1719 }
1720 if(not $Path and $BinUtils{$Name})
1721 {
1722 if($CrossPrefix)
1723 { # user-defined prefix
1724 $Path = search_Cmd($CrossPrefix."-".$Name);
1725 }
1726 }
1727 if(not $Path and $BinUtils{$Name})
1728 {
1729 if(my $Candidate = synch_Cmd($Name))
1730 { # synch with GCC
1731 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001732 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733 if(-f $Candidate) {
1734 $Path = $Candidate;
1735 }
1736 }
1737 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001738 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001739 $Path = $Candidate;
1740 }
1741 }
1742 }
1743 if(not $Path) {
1744 $Path = search_Cmd($Name);
1745 }
1746 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001747 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 $Path=search_Cmd($Name.".exe");
1749 }
1750 if($Path=~/\s/) {
1751 $Path = "\"".$Path."\"";
1752 }
1753 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1754}
1755
1756sub search_Cmd($)
1757{
1758 my $Name = $_[0];
1759 return "" if(not $Name);
1760 if(defined $Cache{"search_Cmd"}{$Name}) {
1761 return $Cache{"search_Cmd"}{$Name};
1762 }
1763 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1764 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1765 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001766 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001768 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001769 if(-f $CmdPath)
1770 {
1771 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001772 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001773 }
1774 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1775 }
1776 }
1777 return ($Cache{"search_Cmd"}{$Name} = "");
1778}
1779
1780sub get_CmdPath_Default($)
1781{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001782 return "" if(not $_[0]);
1783 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1784 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001786 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1787}
1788
1789sub get_CmdPath_Default_I($)
1790{ # search in PATH
1791 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 if($Name=~/find/)
1793 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001794 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001795 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 }
1797 }
1798 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001799 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001800 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001801 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001802 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001804 if($OSgroup eq "windows")
1805 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001806 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001807 return $Name;
1808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001809 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001810 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001811 {
1812 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001813 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 }
1815 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001816 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001817}
1818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819sub classifyPath($)
1820{
1821 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001822 if($Path=~/[\*\+\(\[\|]/)
1823 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 return ($Path, "Pattern");
1825 }
1826 elsif($Path=~/[\/\\]/)
1827 { # directory or relative path
1828 return (path_format($Path, $OSgroup), "Path");
1829 }
1830 else {
1831 return ($Path, "Name");
1832 }
1833}
1834
1835sub readDescriptor($$)
1836{
1837 my ($LibVersion, $Content) = @_;
1838 return if(not $LibVersion);
1839 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1840 if(not $Content) {
1841 exitStatus("Error", "$DName is empty");
1842 }
1843 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001844 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001845 }
1846 $Content=~s/\/\*(.|\n)+?\*\///g;
1847 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001848
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001849 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1850 if($TargetVersion{$LibVersion}) {
1851 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1852 }
1853 if(not $Descriptor{$LibVersion}{"Version"}) {
1854 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1855 }
1856 if($Content=~/{RELPATH}/)
1857 {
1858 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1859 $Content =~ s/{RELPATH}/$RelDir/g;
1860 }
1861 else
1862 {
1863 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1864 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1865 }
1866 }
1867
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001868 my $DHeaders = parseTag(\$Content, "headers");
1869 if(not $DHeaders) {
1870 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1871 }
1872 elsif(lc($DHeaders) ne "none")
1873 { # append the descriptor headers list
1874 if($Descriptor{$LibVersion}{"Headers"})
1875 { # multiple descriptors
1876 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001878 else {
1879 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1880 }
1881 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1882 {
1883 if(not -e $Path) {
1884 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 }
1886 }
1887 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 if(not $CheckHeadersOnly_Opt)
1890 {
1891 my $DObjects = parseTag(\$Content, "libs");
1892 if(not $DObjects) {
1893 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1894 }
1895 elsif(lc($DObjects) ne "none")
1896 { # append the descriptor libraries list
1897 if($Descriptor{$LibVersion}{"Libs"})
1898 { # multiple descriptors
1899 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1900 }
1901 else {
1902 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1903 }
1904 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1905 {
1906 if(not -e $Path) {
1907 exitStatus("Access_Error", "can't access \'$Path\'");
1908 }
1909 }
1910 }
1911 }
1912 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1913 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 if(not -d $Path) {
1915 exitStatus("Access_Error", "can't access directory \'$Path\'");
1916 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001917 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001918 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001919 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 }
1921 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1922 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 if(not -d $Path) {
1924 exitStatus("Access_Error", "can't access directory \'$Path\'");
1925 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001926 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001927 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001928 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 }
1930 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1931 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 if(not -d $Path) {
1933 exitStatus("Access_Error", "can't access directory \'$Path\'");
1934 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001935 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001937 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001938 $TargetTools{$Path}=1;
1939 }
1940 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1941 $CrossPrefix = $Prefix;
1942 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001943 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1945 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001946 if(not -d $Path) {
1947 exitStatus("Access_Error", "can't access directory \'$Path\'");
1948 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001949 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001950 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001951 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001953 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001954 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1955 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001956 if(not -d $Path) {
1957 exitStatus("Access_Error", "can't access directory \'$Path\'");
1958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001959 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001960 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001961 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001962 }
1963 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001964 { # skip some auto-generated include paths
1965 if(not is_abs($Path))
1966 {
1967 if(my $P = abs_path($Path)) {
1968 $Path = $P;
1969 }
1970 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001971 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 }
1973 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001974 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001975 my ($CPath, $Type) = classifyPath($Path);
1976 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001977 }
1978 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001979 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1980 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001981 if($Option!~/\A\-(Wl|l|L)/)
1982 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001983 $CompilerOptions{$LibVersion} .= " ".$Option;
1984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001985 }
1986 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1987 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1988 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001989 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001991 my ($CPath, $Type) = classifyPath($Path);
1992 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 }
1994 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1995 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1996 {
1997 my ($CPath, $Type) = classifyPath($Path);
1998 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1999 }
2000 if(my $DDefines = parseTag(\$Content, "defines"))
2001 {
2002 if($Descriptor{$LibVersion}{"Defines"})
2003 { # multiple descriptors
2004 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2005 }
2006 else {
2007 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2008 }
2009 }
2010 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2011 {
2012 if($Order=~/\A(.+):(.+)\Z/) {
2013 $Include_Order{$LibVersion}{$1} = $2;
2014 }
2015 }
2016 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2017 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002018 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002019 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2020 }
2021 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2022 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002023 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2025 }
2026 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2027 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2028 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002029 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2030 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2033 $SkipConstants{$LibVersion}{$Constant} = 1;
2034 }
2035 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2036 {
2037 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002038 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2040 }
2041 else {
2042 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2043 }
2044 }
2045}
2046
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002047sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002049 my $CodeRef = shift(@_);
2050 my $Tag = shift(@_);
2051 if(not $Tag or not $CodeRef) {
2052 return undef;
2053 }
2054 my $Sp = 0;
2055 if(@_) {
2056 $Sp = shift(@_);
2057 }
2058 my $Start = index(${$CodeRef}, "<$Tag>");
2059 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002061 my $End = index(${$CodeRef}, "</$Tag>");
2062 if($End!=-1)
2063 {
2064 my $TS = length($Tag)+3;
2065 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2066 substr($Content, 0, $TS-1, ""); # cut start tag
2067 substr($Content, -$TS, $TS, ""); # cut end tag
2068 if(not $Sp)
2069 {
2070 $Content=~s/\A\s+//g;
2071 $Content=~s/\s+\Z//g;
2072 }
2073 if(substr($Content, 0, 1) ne "<") {
2074 $Content = xmlSpecChars_R($Content);
2075 }
2076 return $Content;
2077 }
2078 }
2079 return undef;
2080}
2081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002082sub getInfo($)
2083{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002084 my $DumpPath = $_[0];
2085 return if(not $DumpPath or not -f $DumpPath);
2086
2087 readTUDump($DumpPath);
2088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002089 # processing info
2090 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002091
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002092 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002093 setAnonTypedef_All();
2094 }
2095
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002096 getTypeInfo_All();
2097 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002098 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002099 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002100 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002101
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002102 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002103 %LibInfo = ();
2104 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002105 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002106 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002107 %TemplateDecl = ();
2108 %StdCxxTypedef = ();
2109 %MissedTypedef = ();
2110 %Typedef_Tr = ();
2111 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002112 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002114 # clean cache
2115 delete($Cache{"getTypeAttr"});
2116 delete($Cache{"getTypeDeclId"});
2117
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002118 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002119 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002120 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002121 }
2122 else
2123 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002124 if($BinaryOnly and not $ExtendedCheck)
2125 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002126 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002127 }
2128 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002129 remove_Unused($Version, "Extended");
2130 }
2131 }
2132
2133 if($CheckInfo)
2134 {
2135 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2136 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2137 }
2138
2139 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2140 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002142 }
2143
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002144 if($Debug) {
2145 # debugMangling($Version);
2146 }
2147}
2148
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002149sub readTUDump($)
2150{
2151 my $DumpPath = $_[0];
2152
2153 open(TU_DUMP, $DumpPath);
2154 local $/ = undef;
2155 my $Content = <TU_DUMP>;
2156 close(TU_DUMP);
2157
2158 unlink($DumpPath);
2159
2160 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002161 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002162
2163 # clean memory
2164 undef $Content;
2165
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002166 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002167
2168 foreach (0 .. $#Lines)
2169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002170 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002171 { # get a number and attributes of a node
2172 next if(not $NodeType{$2});
2173 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002174 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002175 }
2176
2177 # clean memory
2178 delete($Lines[$_]);
2179 }
2180
2181 # clean memory
2182 undef @Lines;
2183}
2184
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002185sub simplifyConstants()
2186{
2187 foreach my $Constant (keys(%{$Constants{$Version}}))
2188 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002189 if(defined $Constants{$Version}{$Constant}{"Header"})
2190 {
2191 my $Value = $Constants{$Version}{$Constant}{"Value"};
2192 if(defined $EnumConstants{$Version}{$Value}) {
2193 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2194 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002195 }
2196 }
2197}
2198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002199sub simplifyNames()
2200{
2201 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2202 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002203 if($Typedef_Eq{$Version}{$Base}) {
2204 next;
2205 }
2206 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2207 if($#Translations==0)
2208 {
2209 if(length($Translations[0])<=length($Base)) {
2210 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2211 }
2212 }
2213 else
2214 { # select most appropriate
2215 foreach my $Tr (@Translations)
2216 {
2217 if($Base=~/\A\Q$Tr\E/)
2218 {
2219 $Typedef_Eq{$Version}{$Base} = $Tr;
2220 last;
2221 }
2222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002223 }
2224 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002225 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002227 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002228 if(not $TypeName) {
2229 next;
2230 }
2231 next if(index($TypeName,"<")==-1);# template instances only
2232 if($TypeName=~/>(::\w+)+\Z/)
2233 { # skip unused types
2234 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002236 foreach my $Base (sort {length($b)<=>length($a)}
2237 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002239 next if(not $Base);
2240 next if(index($TypeName,$Base)==-1);
2241 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002242 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002243 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002244 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2245 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2246 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002247 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002248 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2249 {
2250 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2251 {
2252 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2253 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002254 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002255 }
2256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002259 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002260 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002261 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2262 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002263 }
2264}
2265
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002266sub setAnonTypedef_All()
2267{
2268 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2269 {
2270 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2271 {
2272 if(isAnon(getNameByInfo($InfoId))) {
2273 $TypedefToAnon{getTypeId($InfoId)} = 1;
2274 }
2275 }
2276 }
2277}
2278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002279sub setTemplateParams_All()
2280{
2281 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2282 {
2283 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2284 setTemplateParams($_);
2285 }
2286 }
2287}
2288
2289sub setTemplateParams($)
2290{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002291 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002292 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002293 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002294 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002296 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002297 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002298 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002299 setTemplateInstParams($_[0], $TmplInst_Id);
2300 }
2301 }
2302
2303 $BasicTemplate{$Version}{$Tid} = $_[0];
2304
2305 if(my $Prms = getTreeAttr_Prms($_[0]))
2306 {
2307 if(my $Valu = getTreeAttr_Valu($Prms))
2308 {
2309 my $Vector = getTreeVec($Valu);
2310 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2311 {
2312 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2313 {
2314 if(my $Name = getNameByInfo($Val))
2315 {
2316 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2317 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2318 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2319 }
2320 else {
2321 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2322 }
2323 }
2324 }
2325 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002327 }
2328 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002329 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002330 {
2331 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2332 {
2333 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002334 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002335 }
2336 }
2337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002338}
2339
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002340sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002342 my ($Tmpl, $Inst) = @_;
2343
2344 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002346 my ($Params_InfoId, $ElemId) = ();
2347 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2348 $Params_InfoId = $1;
2349 }
2350 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2351 $ElemId = $1;
2352 }
2353 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002354 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002355 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2356 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2357 {
2358 my ($PPos, $PTypeId) = ($1, $2);
2359 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2360 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002361 if($PType eq "template_type_parm") {
2362 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002363 }
2364 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002365 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2366 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002368 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002370 else
2371 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002373 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 }
2376 }
2377 }
2378}
2379
2380sub getTypeDeclId($)
2381{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002382 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002384 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2385 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2386 }
2387 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2388 {
2389 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2390 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2391 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002394 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002395}
2396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002397sub getTypeInfo_All()
2398{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002399 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002400 { # support for GCC < 4.5
2401 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2402 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2403 # FIXME: check GCC versions
2404 addMissedTypes_Pre();
2405 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002407 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002408 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002409 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2410 if($IType=~/_type\Z/ and $IType ne "function_type"
2411 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002412 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002413 }
2414 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002415
2416 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002417 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002418 "Name" => "...",
2419 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002420 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002421 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002422 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002423
2424 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002425 { # support for GCC < 4.5
2426 addMissedTypes_Post();
2427 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002428
2429 if($ADD_TMPL_INSTANCES)
2430 {
2431 # templates
2432 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2433 {
2434 if(defined $TemplateMap{$Version}{$Tid}
2435 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2436 {
2437 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2438 {
2439 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2440 {
2441 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2442 {
2443 if(my %MAttr = getTypeAttr($MembTypeId))
2444 {
2445 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2446 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2447 }
2448 }
2449 }
2450 }
2451 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2452 {
2453 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2454 {
2455 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2456
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002457 if($NBid ne $Bid
2458 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002459 {
2460 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2461 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2462 }
2463 }
2464 }
2465 }
2466 }
2467 }
2468}
2469
2470sub createType($$)
2471{
2472 my ($Attr, $LibVersion) = @_;
2473 my $NewId = ++$MAX_ID;
2474
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002475 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002476 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002477 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002478
2479 return "$NewId";
2480}
2481
2482sub instType($$$)
2483{ # create template instances
2484 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002485
2486 if(not $TypeInfo{$LibVersion}{$Tid}) {
2487 return undef;
2488 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002489 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2490
2491 foreach my $Key (sort keys(%{$Map}))
2492 {
2493 if(my $Val = $Map->{$Key})
2494 {
2495 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2496
2497 if(defined $Attr->{"NameSpace"}) {
2498 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2499 }
2500 foreach (keys(%{$Attr->{"TParam"}})) {
2501 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2502 }
2503 }
2504 else
2505 { # remove absent
2506 # _Traits, etc.
2507 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002508 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002509 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2510 }
2511 foreach (keys(%{$Attr->{"TParam"}}))
2512 {
2513 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2514 delete($Attr->{"TParam"}{$_});
2515 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002516 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002517 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2518 }
2519 }
2520 }
2521 }
2522
2523 my $Tmpl = 0;
2524
2525 if(defined $Attr->{"TParam"})
2526 {
2527 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2528 {
2529 my $PName = $Attr->{"TParam"}{$_}{"name"};
2530
2531 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2532 {
2533 my %Base = get_BaseType($PTid, $LibVersion);
2534
2535 if($Base{"Type"} eq "TemplateParam"
2536 or defined $Base{"Template"})
2537 {
2538 $Tmpl = 1;
2539 last
2540 }
2541 }
2542 }
2543 }
2544
2545 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2546 return "$Id";
2547 }
2548 else
2549 {
2550 if(not $Tmpl) {
2551 delete($Attr->{"Template"});
2552 }
2553
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002554 my $New = createType($Attr, $LibVersion);
2555
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002556 my %EMap = ();
2557 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2558 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2559 }
2560 foreach (keys(%{$Map})) {
2561 $EMap{$_} = $Map->{$_};
2562 }
2563
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002564 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2565 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002566 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002567 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002568 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002569 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002570 {
2571 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2572
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002573 if($NBid ne $Bid
2574 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002575 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002576 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2577 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002578 }
2579 }
2580 }
2581
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002582 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002583 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002584 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2585 {
2586 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2587 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2588 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 }
2590 }
2591
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002592 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002594 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2595 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002596 }
2597 }
2598
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002599 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2600 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002601 }
2602
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002603 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605}
2606
2607sub addMissedTypes_Pre()
2608{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2611 { # detecting missed typedefs
2612 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002614 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002616 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 if($TypeType eq "Unknown")
2618 { # template_type_parm
2619 next;
2620 }
2621 my $TypeDeclId = getTypeDeclId($TypeId);
2622 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2623 my $TypedefName = getNameByInfo($MissedTDid);
2624 next if(not $TypedefName);
2625 next if($TypedefName eq "__float80");
2626 next if(isAnon($TypedefName));
2627 if(not $TypeDeclId
2628 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002629 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 }
2631 }
2632 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002634 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002636 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002638 next;
2639 }
2640 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002642 if(not $TypedefName) {
2643 next;
2644 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002645 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 my %MissedInfo = ( # typedef info
2647 "Name" => $TypedefName,
2648 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002649 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002651 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 my ($H, $L) = getLocation($MissedTDid);
2653 $MissedInfo{"Header"} = $H;
2654 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 { # other types
2657 next;
2658 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002659 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002661 next;
2662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002663 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002665 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002667 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669 next;
2670 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002671 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 next;
2673 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002674 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676 next;
2677 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002678 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002679 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 next;
2681 }
2682 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002683
2684 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002689 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002691
2692 # add missed & remove other
2693 $TypeInfo{$Version} = \%AddTypes;
2694 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002695}
2696
2697sub addMissedTypes_Post()
2698{
2699 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2700 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002701 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2702 {
2703 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2704 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2705 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2706 }
2707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708 }
2709}
2710
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002713 my $TypeId = $_[0];
2714 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2715 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002717 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002719}
2720
2721sub getArraySize($$)
2722{
2723 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002724 if(my $Size = getSize($TypeId))
2725 {
2726 my $Elems = $Size/$BYTE_SIZE;
2727 while($BaseName=~s/\s*\[(\d+)\]//) {
2728 $Elems/=$1;
2729 }
2730 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2731 {
2732 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2733 $Elems/=$BasicSize;
2734 }
2735 }
2736 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002739}
2740
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2746 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002747 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2749 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2750 if(not $NodeType)
2751 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 return ();
2753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002754 if($NodeType eq "tree_vec")
2755 {
2756 if($Pos!=$#Positions)
2757 { # select last vector of parameters ( ns<P1>::type<P2> )
2758 next;
2759 }
2760 }
2761 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2762 foreach my $P (@Params)
2763 {
2764 if($P eq "") {
2765 return ();
2766 }
2767 elsif($P ne "\@skip\@") {
2768 @TmplParams = (@TmplParams, $P);
2769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 }
2771 }
2772 return @TmplParams;
2773}
2774
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002776{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002777 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002778 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002779 if(defined $TypeInfo{$Version}{$TypeId}
2780 and $TypeInfo{$Version}{$TypeId}{"Name"})
2781 { # already created
2782 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002784 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2785 { # incomplete type
2786 return ();
2787 }
2788 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2789
2790 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002791 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002792
2793 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2794 {
2795 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2796 {
2797 if($Info=~/qual[ ]*:/)
2798 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002799 my $NewId = ++$MAX_ID;
2800
2801 $MissedBase{$Version}{$TypeId} = "$NewId";
2802 $MissedBase_R{$Version}{$NewId} = $TypeId;
2803 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2804 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002805 }
2806 }
2807 $TypeAttr{"Type"} = "Typedef";
2808 }
2809 else {
2810 $TypeAttr{"Type"} = getTypeType($TypeId);
2811 }
2812
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002813 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2814 {
2815 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2816 { # local code
2817 return ();
2818 }
2819 }
2820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 if($TypeAttr{"Type"} eq "Unknown") {
2822 return ();
2823 }
2824 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2825 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002827 if(my $TName = $TypeAttr{"Name"})
2828 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002830 $TName_Tid{$Version}{$TName} = $TypeId;
2831 return %TypeAttr;
2832 }
2833 else {
2834 return ();
2835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002836 }
2837 elsif($TypeAttr{"Type"} eq "Array")
2838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002839 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2840 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002841 return ();
2842 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002843 if(my $Algn = getAlgn($TypeId)) {
2844 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2845 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002846 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002847 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002849 if(not $BTAttr{"Name"}) {
2850 return ();
2851 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002852 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002853 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002854 if(my $Size = getSize($TypeId)) {
2855 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2856 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002857 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002858 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2859 }
2860 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002861 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002864 else
2865 {
2866 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002867 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002868 $TypeAttr{"Name"} = $1."[]".$2;
2869 }
2870 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002871 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002873 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002874 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002875 if($BTAttr{"Header"}) {
2876 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002877 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002879 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2880 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002881 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002882 return ();
2883 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002884 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002885 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002887 if($TypeAttr{"Name"})
2888 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002889 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002890
2891 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2892 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002893 { # NOTE: register only one int: with built-in decl
2894 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2895 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2896 }
2897 }
2898 return %TypeAttr;
2899 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002900 else {
2901 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002904 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2905 {
2906 %TypeAttr = getTrivialTypeAttr($TypeId);
2907 if($TypeAttr{"Name"})
2908 {
2909 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2910 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2911 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2912 }
2913 return %TypeAttr;
2914 }
2915 else {
2916 return ();
2917 }
2918 }
2919 elsif($TypeAttr{"Type"} eq "SizeOf")
2920 {
2921 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2922 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2923 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2924 if($TypeAttr{"Name"})
2925 {
2926 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2927 return %TypeAttr;
2928 }
2929 else {
2930 return ();
2931 }
2932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002934 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002935 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2936 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002937 return ();
2938 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002939 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002940 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002943 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002944 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002945 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002947 }
2948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002949 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002951 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002952 return ();
2953 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002954 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002955 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002956 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002957 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002958 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002959 }
2960 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002961 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002962 {
2963 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002966 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002967 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2968 }
2969 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002971 }
2972 }
2973 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002975 }
2976 if($TypeAttr{"Type"} eq "Typedef")
2977 {
2978 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002979
2980 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2981 return ();
2982 }
2983
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002984 if(isAnon($TypeAttr{"Name"}))
2985 { # anon typedef to anon type: ._N
2986 return ();
2987 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002988
2989 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2990 { # artificial typedef of "struct X" to "X"
2991 $TypeAttr{"Artificial"} = 1;
2992 }
2993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 if(my $NS = getNameSpace($TypeDeclId))
2995 {
2996 my $TypeName = $TypeAttr{"Name"};
2997 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2998 { # "some_type" is the typedef to "struct some_type" in C++
2999 if($3) {
3000 $TypeAttr{"Name"} = $3."::".$TypeName;
3001 }
3002 }
3003 else
3004 {
3005 $TypeAttr{"NameSpace"} = $NS;
3006 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003007
3008 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3009 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3010 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003011 if($BTAttr{"NameSpace"}
3012 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003013 { # types like "std::fpos<__mbstate_t>" are
3014 # not covered by typedefs in the TU dump
3015 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003016 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3017 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003018 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003019 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003020 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003021 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003023 }
3024 }
3025 }
3026 }
3027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003028 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003029 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003031 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3032 { # typedef int*const TYPEDEF; // first
3033 # int foo(TYPEDEF p); // const is optimized out
3034 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3035 if($BTAttr{"Name"}=~/</)
3036 {
3037 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3038 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 }
3041 }
3042 }
3043 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3044 }
3045 if(not $TypeAttr{"Size"})
3046 {
3047 if($TypeAttr{"Type"} eq "Pointer") {
3048 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3049 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003050 elsif($BTAttr{"Size"}) {
3051 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
3053 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003054 if(my $Algn = getAlgn($TypeId)) {
3055 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3056 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003057 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003058 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3059 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003061 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003062 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003063 { # typedef to "class Class"
3064 # should not be registered in TName_Tid
3065 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3066 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003068 }
3069 return %TypeAttr;
3070 }
3071}
3072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003073sub getTreeVec($)
3074{
3075 my %Vector = ();
3076 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3077 {
3078 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3079 { # string length is N-1 because of the null terminator
3080 $Vector{$1} = $2;
3081 }
3082 }
3083 return \%Vector;
3084}
3085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003086sub get_TemplateParam($$)
3087{
3088 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003089 return () if(not $Type_Id);
3090 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3091 return () if(not $NodeType);
3092 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003095 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003096 my $Num = getNodeIntCst($Type_Id);
3097 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003098 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003099 }
3100 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003101 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 }
3103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003104 elsif($NodeType eq "string_cst") {
3105 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 elsif($NodeType eq "tree_vec")
3108 {
3109 my $Vector = getTreeVec($Type_Id);
3110 my @Params = ();
3111 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3112 {
3113 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3114 push(@Params, $P2);
3115 }
3116 }
3117 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003118 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003119 elsif($NodeType eq "parm_decl")
3120 {
3121 (getNameByInfo($Type_Id));
3122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 else
3124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003125 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003126 my $PName = $ParamAttr{"Name"};
3127 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003128 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003129 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003130 if($PName=~/\>/)
3131 {
3132 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003133 $PName = $Cover;
3134 }
3135 }
3136 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003137 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003138 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3139 # template<typename _Key, typename _Compare = std::less<_Key>
3140 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3141 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3142 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3143 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003144 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003146 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003147 }
3148}
3149
3150sub cover_stdcxx_typedef($)
3151{
3152 my $TypeName = $_[0];
3153 if(my @Covers = sort {length($a)<=>length($b)}
3154 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3155 { # take the shortest typedef
3156 # FIXME: there may be more than
3157 # one typedefs to the same type
3158 return $Covers[0];
3159 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003160 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003161 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3162 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3163 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003164 if(my $Cover = $Covers[0])
3165 {
3166 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3167 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003170 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171}
3172
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173sub getNodeIntCst($)
3174{
3175 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003177 if($EnumMembName_Id{$Version}{$CstId}) {
3178 return $EnumMembName_Id{$Version}{$CstId};
3179 }
3180 elsif((my $Value = getTreeValue($CstId)) ne "")
3181 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003182 if($Value eq "0")
3183 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003184 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185 return "false";
3186 }
3187 else {
3188 return "0";
3189 }
3190 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003191 elsif($Value eq "1")
3192 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003193 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003194 return "true";
3195 }
3196 else {
3197 return "1";
3198 }
3199 }
3200 else {
3201 return $Value;
3202 }
3203 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205}
3206
3207sub getNodeStrCst($)
3208{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003209 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3210 {
3211 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003212 {
3213 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3214 { # string length is N-1 because of the null terminator
3215 return substr($1, 0, $2-1);
3216 }
3217 else
3218 { # identifier_node
3219 return substr($1, 0, $2);
3220 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003222 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003223 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003224}
3225
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003226sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003227{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003228 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3230 if($Type eq "FieldPtr") {
3231 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3232 }
3233 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3234 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003235 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003236 if($Type eq "MethodPtr")
3237 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003238 if(my $Size = getSize($TypeId))
3239 {
3240 $Size/=$BYTE_SIZE;
3241 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003243 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003244 if(my $Algn = getAlgn($TypeId)) {
3245 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003247 # Return
3248 if($Type eq "FieldPtr")
3249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003250 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 if($ReturnAttr{"Name"}) {
3252 $MemPtrName .= $ReturnAttr{"Name"};
3253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 $TypeAttr{"Return"} = $PtrId;
3255 }
3256 else
3257 {
3258 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3259 {
3260 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003261 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3262 if(not $ReturnAttr{"Name"})
3263 { # templates
3264 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003266 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003267 $TypeAttr{"Return"} = $ReturnTypeId;
3268 }
3269 }
3270 # Class
3271 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3272 {
3273 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003274 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003275 if($Class{"Name"}) {
3276 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3277 }
3278 else {
3279 $MemPtrName .= " (*)";
3280 }
3281 }
3282 else {
3283 $MemPtrName .= " (*)";
3284 }
3285 # Parameters
3286 if($Type eq "FuncPtr"
3287 or $Type eq "MethodPtr")
3288 {
3289 my @ParamTypeName = ();
3290 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3291 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003292 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003293 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003294 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003295 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003296 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3297 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003299 my $PTypeId = $1;
3300 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003301 if(not $ParamAttr{"Name"})
3302 { # templates (template_type_parm), etc.
3303 return ();
3304 }
3305 if($ParamAttr{"Name"} eq "void") {
3306 last;
3307 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003308 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003309 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003310 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003311 push(@ParamTypeName, $ParamAttr{"Name"});
3312 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003313 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3314 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003315 }
3316 else {
3317 last;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003320 else {
3321 last;
3322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
3324 }
3325 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3326 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003327 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003328 return %TypeAttr;
3329}
3330
3331sub getTreeTypeName($)
3332{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003333 my $TypeId = $_[0];
3334 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003336 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003338 if(my $Name = getNameByInfo($TypeId))
3339 { # bit_size_type
3340 return $Name;
3341 }
3342 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003343 return "unsigned int";
3344 }
3345 else {
3346 return "int";
3347 }
3348 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003349 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003350 return getNameByInfo($1);
3351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003352 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003353 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003354}
3355
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003356sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003358 my $Ptd = pointTo($_[0]);
3359 return 0 if(not $Ptd);
3360 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003361 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003362 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3363 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003364 }
3365 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003366 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3367 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003368 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003369 if($InfoT1 eq "pointer_type"
3370 and $InfoT2 eq "function_type") {
3371 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003372 }
3373 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003374 return 0;
3375}
3376
3377sub isMethodPtr($)
3378{
3379 my $Ptd = pointTo($_[0]);
3380 return 0 if(not $Ptd);
3381 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3382 {
3383 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3384 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3385 and $Info=~/ ptrmem /) {
3386 return 1;
3387 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003388 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003389 return 0;
3390}
3391
3392sub isFieldPtr($)
3393{
3394 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3395 {
3396 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3397 and $Info=~/ ptrmem /) {
3398 return 1;
3399 }
3400 }
3401 return 0;
3402}
3403
3404sub pointTo($)
3405{
3406 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3407 {
3408 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3409 return $1;
3410 }
3411 }
3412 return "";
3413}
3414
3415sub getTypeTypeByTypeId($)
3416{
3417 my $TypeId = $_[0];
3418 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3419 {
3420 my $NType = $NodeType{$TType};
3421 if($NType eq "Intrinsic") {
3422 return $NType;
3423 }
3424 elsif(isFuncPtr($TypeId)) {
3425 return "FuncPtr";
3426 }
3427 elsif(isMethodPtr($TypeId)) {
3428 return "MethodPtr";
3429 }
3430 elsif(isFieldPtr($TypeId)) {
3431 return "FieldPtr";
3432 }
3433 elsif($NType ne "Other") {
3434 return $NType;
3435 }
3436 }
3437 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438}
3439
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003440my %UnQual = (
3441 "r"=>"restrict",
3442 "v"=>"volatile",
3443 "c"=>"const",
3444 "cv"=>"const volatile"
3445);
3446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003447sub getQual($)
3448{
3449 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003450 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3451 {
3452 my ($Qual, $To) = ();
3453 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3454 $Qual = $UnQual{$1};
3455 }
3456 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3457 $To = $1;
3458 }
3459 if($Qual and $To) {
3460 return ($Qual, $To);
3461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003462 }
3463 return ();
3464}
3465
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003466sub getQualType($)
3467{
3468 if($_[0] eq "const volatile") {
3469 return "ConstVolatile";
3470 }
3471 return ucfirst($_[0]);
3472}
3473
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003474sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003475{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003476 my $TypeId = $_[0];
3477 my $TypeDeclId = getTypeDeclId($TypeId);
3478 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003479 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003480 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3481 return "Typedef";
3482 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003483 }
3484 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3485 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003486 if(($Qual or $To) and $TypeDeclId
3487 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003488 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003490 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003491 elsif(not $MissedBase_R{$Version}{$TypeId}
3492 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003493 return "Typedef";
3494 }
3495 elsif($Qual)
3496 { # qualified types
3497 return getQualType($Qual);
3498 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003499
3500 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3501 { # typedef struct { ... } name
3502 $TypeTypedef{$Version}{$TypeId} = $1;
3503 }
3504
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003505 my $TypeType = getTypeTypeByTypeId($TypeId);
3506 if($TypeType eq "Struct")
3507 {
3508 if($TypeDeclId
3509 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3510 return "Template";
3511 }
3512 }
3513 return $TypeType;
3514}
3515
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003516sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003517{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003518 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003519 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003520 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3521 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3522 return 0;
3523 }
3524 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3525 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003526 if(my $TDid = getTypeDeclId($_[0]))
3527 {
3528 if(getTypeId($TDid) eq $_[0]
3529 and getNameByInfo($TDid))
3530 {
3531 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3532 return $1;
3533 }
3534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 }
3537 }
3538 return 0;
3539}
3540
3541sub selectBaseType($)
3542{
3543 my $TypeId = $_[0];
3544 if(defined $MissedTypedef{$Version}{$TypeId})
3545 { # add missed typedefs
3546 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3547 return ($TypeId, "");
3548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003550 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3551 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552
3553 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3554 my $MB = $MissedBase{$Version}{$TypeId};
3555
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003556 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003557 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003558 and (getTypeId($1) ne $TypeId)
3559 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003561 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 elsif($MB)
3564 { # add base
3565 return ($MB, "");
3566 }
3567 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003568 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003569 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003571 elsif($Qual or $To)
3572 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003573 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003575 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003576 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003577 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003578 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003580 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003581 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003583 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003584 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003586 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003587 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003589 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003590 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003592 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003593
3594 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003595}
3596
3597sub getSymbolInfo_All()
3598{
3599 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3600 { # reverse order
3601 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003602 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003603 }
3604 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003605
3606 if($ADD_TMPL_INSTANCES)
3607 {
3608 # templates
3609 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3610 {
3611 my %Map = ();
3612
3613 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3614 {
3615 if(defined $TemplateMap{$Version}{$ClassId})
3616 {
3617 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3618 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3619 }
3620 }
3621 }
3622
3623 if(defined $TemplateMap{$Version}{$Sid})
3624 {
3625 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3626 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3627 }
3628 }
3629
3630 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3631 {
3632 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3633 {
3634 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3635 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3636 }
3637 }
3638 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3639 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3640 }
3641 }
3642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003643}
3644
3645sub getVarInfo_All()
3646{
3647 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3648 { # reverse order
3649 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003651 }
3652 }
3653}
3654
3655sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003656 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657}
3658
3659sub getVarInfo($)
3660{
3661 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003662 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003663 {
3664 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3665 if($NSInfoType and $NSInfoType eq "function_decl") {
3666 return;
3667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 }
3669 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3670 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3671 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3672 delete($SymbolInfo{$Version}{$InfoId});
3673 return;
3674 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003675 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003676 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 delete($SymbolInfo{$Version}{$InfoId});
3678 return;
3679 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003680 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3681 delete($SymbolInfo{$Version}{$InfoId});
3682 return;
3683 }
3684 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003685 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3686 {
3687 if($OSgroup eq "windows")
3688 { # cut the offset
3689 $MnglName=~s/\@\d+\Z//g;
3690 }
3691 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003693 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003694 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 { # validate mangled name
3696 delete($SymbolInfo{$Version}{$InfoId});
3697 return;
3698 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003699 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003700 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003701 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003702 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003703 }
3704 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3705 { # non-public global data
3706 delete($SymbolInfo{$Version}{$InfoId});
3707 return;
3708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003710 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003711 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003712 if(not defined $TypeInfo{$Version}{$Rid}
3713 or not $TypeInfo{$Version}{$Rid}{"Name"})
3714 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003715 delete($SymbolInfo{$Version}{$InfoId});
3716 return;
3717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003718 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3719 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003720 if(defined $Val) {
3721 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003723 }
3724 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003725 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3726 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003727 if(not defined $TypeInfo{$Version}{$ClassId}
3728 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3729 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003730 delete($SymbolInfo{$Version}{$InfoId});
3731 return;
3732 }
3733 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003734 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3735 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003737 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003738 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003739 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003741 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003743 if(not $CheckHeadersOnly)
3744 {
3745 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3746 {
3747 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3748 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3749 {
3750 if(link_symbol($ShortName, $Version, "-Deps"))
3751 { # "const" global data is mangled as _ZL... in the TU dump
3752 # but not mangled when compiling a C shared library
3753 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3754 }
3755 }
3756 }
3757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003758 if($COMMON_LANGUAGE{$Version} eq "C++")
3759 {
3760 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3761 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003762 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3764 }
3765 }
3766 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3767 { # try to mangle symbol (link with libraries)
3768 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3769 }
3770 if($OStarget eq "windows")
3771 {
3772 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3773 { # link MS C++ symbols from library with GCC symbols from headers
3774 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3775 }
3776 }
3777 }
3778 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3779 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3780 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003781 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3782 {
3783 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3784 { # non-target symbols
3785 delete($SymbolInfo{$Version}{$InfoId});
3786 return;
3787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003788 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003789 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3790 {
3791 if(defined $MissedTypedef{$Version}{$Rid})
3792 {
3793 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3794 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3795 }
3796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 }
3798 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003799 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003800 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3801 }
3802 if($ShortName=~/\A(_Z|\?)/) {
3803 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3804 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003805
3806 if($ExtraDump) {
3807 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003809}
3810
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003811sub isConstType($$)
3812{
3813 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003814 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003815 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003816 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003817 }
3818 return ($Base{"Type"} eq "Const");
3819}
3820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821sub getTrivialName($$)
3822{
3823 my ($TypeInfoId, $TypeId) = @_;
3824 my %TypeAttr = ();
3825 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3826 if(not $TypeAttr{"Name"}) {
3827 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3828 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003829 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003830 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003832 if(isAnon($TypeAttr{"Name"}))
3833 {
3834 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003835 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003836 { # searching for a first not anon scope
3837 if($NSId eq $NameSpaceId) {
3838 last;
3839 }
3840 else
3841 {
3842 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3843 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003844 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003845 last;
3846 }
3847 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003848 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003849 }
3850 }
3851 else
3852 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003853 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003854 {
3855 if($NameSpaceId ne $TypeId) {
3856 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003858 }
3859 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003860 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3862 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003863 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003864 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003865 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003866 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003867 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003868 if($TypeAttr{"NameSpace"}) {
3869 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003871 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003872 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3873 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003874 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003875 if(my @TParams = getTParams($TypeId, "Type")) {
3876 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3877 }
3878 else {
3879 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003881 }
3882 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3883}
3884
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003885sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003886{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003887 my $TypeId = $_[0];
3888 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003889
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003890 my %TypeAttr = ();
3891
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003892 if($TemplateDecl{$Version}{$TypeId})
3893 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003894 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003895 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003897 setTypeAccess($TypeId, \%TypeAttr);
3898 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3899 if(isBuiltIn($TypeAttr{"Header"}))
3900 {
3901 delete($TypeAttr{"Header"});
3902 delete($TypeAttr{"Line"});
3903 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003904
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003905 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003906 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3907 if(not $TypeAttr{"Name"}) {
3908 return ();
3909 }
3910 if(not $TypeAttr{"NameSpace"}) {
3911 delete($TypeAttr{"NameSpace"});
3912 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003913
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003914 if($TypeAttr{"Type"} eq "Intrinsic")
3915 {
3916 if(defined $TypeAttr{"Header"})
3917 {
3918 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3919 { # support for SUSE 11.2
3920 # integer_type has srcp dump{1-2}.i
3921 delete($TypeAttr{"Header"});
3922 }
3923 }
3924 }
3925
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 my $Tmpl = undef;
3927
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003928 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003929 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003930 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3931
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003932 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003933 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003934 foreach my $Pos (0 .. $#TParams)
3935 {
3936 my $Val = $TParams[$Pos];
3937 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3938
3939 if(not defined $TypeAttr{"Template"})
3940 {
3941 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3942
3943 if($Base{"Type"} eq "TemplateParam"
3944 or defined $Base{"Template"}) {
3945 $TypeAttr{"Template"} = 1;
3946 }
3947 }
3948
3949 if($Tmpl)
3950 {
3951 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3952 {
3953 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3954
3955 if($Val eq $Arg) {
3956 $TypeAttr{"Template"} = 1;
3957 }
3958 }
3959 }
3960 }
3961
3962 if($Tmpl)
3963 {
3964 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3965 {
3966 if($Pos>$#TParams)
3967 {
3968 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3969 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3970 }
3971 }
3972 }
3973 }
3974
3975 if($ADD_TMPL_INSTANCES)
3976 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003977 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003978 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003979 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003980 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003981 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003982 {
3983 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3984 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3985 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003986 }
3987 if(not getTreeAttr_Binf($TypeId))
3988 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3990 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3991 }
3992 }
3993 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003994 }
3995 }
3996 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997
3998 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3999
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004000 if(my $Size = getSize($TypeId))
4001 {
4002 $Size = $Size/$BYTE_SIZE;
4003 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004004 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004005 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004006 {
4007 if($ExtraDump)
4008 {
4009 if(not defined $TypeAttr{"Memb"}
4010 and not $Tmpl)
4011 { # declaration only
4012 $TypeAttr{"Forward"} = 1;
4013 }
4014 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004015 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004017 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004018 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004019 {
4020 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004021 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004022 }
4023 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004024 or $TypeAttr{"Type"} eq "Class")
4025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004026 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004027 if($Skip) {
4028 return ();
4029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004030 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004031 if(my $Algn = getAlgn($TypeId)) {
4032 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004034 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004035
4036 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4037 {
4038 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004039 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004040 {
4041 if(not isAnon($TypeAttr{"Name"})) {
4042 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4043 }
4044 }
4045 }
4046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004047 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004048 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4049 {
4050 my @Entries = split(/\n/, $VTable);
4051 foreach (1 .. $#Entries)
4052 {
4053 my $Entry = $Entries[$_];
4054 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004055 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004056 }
4057 }
4058 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004059
4060 if($TypeAttr{"Type"} eq "Enum")
4061 {
4062 if(not $TypeAttr{"NameSpace"})
4063 {
4064 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4065 {
4066 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004067 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004068 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004069 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004070 "Header"=>$TypeAttr{"Header"}
4071 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004072 if(isAnon($TypeAttr{"Name"}))
4073 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004074 if($ExtraDump
4075 or is_target_header($TypeAttr{"Header"}, $Version))
4076 {
4077 %{$Constants{$Version}{$MName}} = (
4078 "Value" => $MVal,
4079 "Header" => $TypeAttr{"Header"}
4080 );
4081 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004082 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004083 }
4084 }
4085 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004086 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004087 {
4088 if(defined $TypedefToAnon{$TypeId}) {
4089 $TypeAttr{"AnonTypedef"} = 1;
4090 }
4091 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 return %TypeAttr;
4094}
4095
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004096sub simplifyVTable($)
4097{
4098 my $Content = $_[0];
4099 if($Content=~s/ \[with (.+)]//)
4100 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4101 if(my @Elems = separate_Params($1, 0, 0))
4102 {
4103 foreach my $Elem (@Elems)
4104 {
4105 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4106 {
4107 my ($Arg, $Val) = ($1, $2);
4108
4109 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4110 $Content=~s/,\s*$Arg\b//g;
4111 }
4112 else {
4113 $Content=~s/\b$Arg\b/$Val/g;
4114 }
4115 }
4116 }
4117 }
4118 }
4119
4120 return $Content;
4121}
4122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123sub detect_lang($)
4124{
4125 my $TypeId = $_[0];
4126 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004127 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004128 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4130 }
4131 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004132 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004133 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 while($Fncs)
4135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004136 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 return 1;
4138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004139 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004140 }
4141 }
4142 return 0;
4143}
4144
4145sub setSpec($$)
4146{
4147 my ($TypeId, $TypeAttr) = @_;
4148 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4149 if($Info=~/\s+spec\s+/) {
4150 $TypeAttr->{"Spec"} = 1;
4151 }
4152}
4153
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004154sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004155{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004156 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004157 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004158 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004160 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004161 my $Pos = 0;
4162 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4163 {
4164 my ($Access, $BInfoId) = ($1, $2);
4165 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004166
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004167 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004168 { # class A<N>:public A<N-1>
4169 next;
4170 }
4171
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004172 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4173 if(not $CType or $CType eq "template_type_parm"
4174 or $CType eq "typename_type")
4175 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004176 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004178 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004179 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004180 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4181 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004182 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004183 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4184 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004185 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004187 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004188 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4189 }
4190 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004191 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 }
4193 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004194 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004195}
4196
4197sub getBinfClassId($)
4198{
4199 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004200 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4201 return $1;
4202 }
4203
4204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004205}
4206
4207sub unmangledFormat($$)
4208{
4209 my ($Name, $LibVersion) = @_;
4210 $Name = uncover_typedefs($Name, $LibVersion);
4211 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4212 $Name=~s/\(\w+\)(\d)/$1/;
4213 return $Name;
4214}
4215
4216sub modelUnmangled($$)
4217{
4218 my ($InfoId, $Compiler) = @_;
4219 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4220 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4221 }
4222 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4223 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4224 $PureSignature = "~".$PureSignature;
4225 }
4226 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4227 {
4228 my (@Params, @ParamTypes) = ();
4229 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4230 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4231 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4232 }
4233 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4234 { # checking parameters
4235 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004236 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004237 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004238 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004239
4240 if($PName eq "this"
4241 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4242 {
4243 next;
4244 }
4245
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004246 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004247 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004248 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 }
4250 @ParamTypes = (@ParamTypes, $PTName);
4251 }
4252 if(@ParamTypes) {
4253 $PureSignature .= "(".join(", ", @ParamTypes).")";
4254 }
4255 else
4256 {
4257 if($Compiler eq "MSVC")
4258 {
4259 $PureSignature .= "(void)";
4260 }
4261 else
4262 { # GCC
4263 $PureSignature .= "()";
4264 }
4265 }
4266 $PureSignature = delete_keywords($PureSignature);
4267 }
4268 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4269 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004270 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004271 $PureSignature = $ClassName."::".$PureSignature;
4272 }
4273 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4274 $PureSignature = $NS."::".$PureSignature;
4275 }
4276 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4277 $PureSignature .= " const";
4278 }
4279 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4280 $PureSignature .= " volatile";
4281 }
4282 my $ShowReturn = 0;
4283 if($Compiler eq "MSVC"
4284 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4285 {
4286 $ShowReturn=1;
4287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004288 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4289 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004290 {
4291 $ShowReturn=1;
4292 }
4293 if($ShowReturn)
4294 { # mangled names for template function specializations include return value
4295 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4296 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004297 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004298 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4299 $PureSignature = $ReturnName." ".$PureSignature;
4300 }
4301 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004302 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004303}
4304
4305sub mangle_symbol($$$)
4306{ # mangling for simple methods
4307 # see gcc-4.6.0/gcc/cp/mangle.c
4308 my ($InfoId, $LibVersion, $Compiler) = @_;
4309 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4310 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4311 }
4312 my $Mangled = "";
4313 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004314 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004315 }
4316 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004317 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004318 }
4319 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4320}
4321
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004322sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004323{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004324 my ($InfoId, $LibVersion) = @_;
4325 return "";
4326}
4327
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004329{ # see gcc-4.6.0/gcc/cp/mangle.c
4330 my ($InfoId, $LibVersion) = @_;
4331 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004332 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004333 my %Repl = ();# SN_ replacements
4334 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4335 {
4336 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4337 if($MangledClass!~/\AN/) {
4338 $MangledClass = "N".$MangledClass;
4339 }
4340 else {
4341 $MangledClass=~s/E\Z//;
4342 }
4343 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4344 $MangledClass=~s/\AN/NV/;
4345 }
4346 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4347 $MangledClass=~s/\AN/NK/;
4348 }
4349 $Mangled .= $MangledClass;
4350 }
4351 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4352 { # mangled by name due to the absence of structured info
4353 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4354 if($MangledNS!~/\AN/) {
4355 $MangledNS = "N".$MangledNS;
4356 }
4357 else {
4358 $MangledNS=~s/E\Z//;
4359 }
4360 $Mangled .= $MangledNS;
4361 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004362 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004363 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004364 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004365 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004366 foreach (@TPos) {
4367 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4368 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004369 }
4370 elsif($TmplParams)
4371 { # remangling mode
4372 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004373 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004374 }
4375 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4376 $Mangled .= "C1";
4377 }
4378 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4379 $Mangled .= "D0";
4380 }
4381 elsif($ShortName)
4382 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004383 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4384 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004385 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004386 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004387 { # "const" global data is mangled as _ZL...
4388 $Mangled .= "L";
4389 }
4390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004391 if($ShortName=~/\Aoperator(\W.*)\Z/)
4392 {
4393 my $Op = $1;
4394 $Op=~s/\A[ ]+//g;
4395 if(my $OpMngl = $OperatorMangling{$Op}) {
4396 $Mangled .= $OpMngl;
4397 }
4398 else { # conversion operator
4399 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4400 }
4401 }
4402 else {
4403 $Mangled .= length($ShortName).$ShortName;
4404 }
4405 if(@TParams)
4406 { # templates
4407 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004408 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4410 }
4411 $Mangled .= "E";
4412 }
4413 if(not $ClassId and @TParams) {
4414 add_substitution($ShortName, \%Repl, 0);
4415 }
4416 }
4417 if($ClassId or $NameSpace) {
4418 $Mangled .= "E";
4419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004420 if(@TParams)
4421 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004422 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004423 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4424 }
4425 }
4426 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4427 {
4428 my @Params = ();
4429 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4430 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4431 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4432 }
4433 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4434 { # checking parameters
4435 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4436 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4437 }
4438 if(not @Params) {
4439 $Mangled .= "v";
4440 }
4441 }
4442 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4443 $Mangled = write_stdcxx_substitution($Mangled);
4444 if($Mangled eq "_Z") {
4445 return "";
4446 }
4447 return $Mangled;
4448}
4449
4450sub correct_incharge($$$)
4451{
4452 my ($InfoId, $LibVersion, $Mangled) = @_;
4453 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4454 {
4455 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004456 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004457 }
4458 }
4459 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4460 {
4461 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004462 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004463 }
4464 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004465 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004466 }
4467 }
4468 return $Mangled;
4469}
4470
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004471sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004472{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004473 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004475 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004476 return $Name;
4477 }
4478 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004479 while(my $CPos = find_center($TParams, "<"))
4480 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004481 $TParams = substr($TParams, $CPos);
4482 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004483 if($TParams=~s/\A<(.+)>\Z/$1/) {
4484 $Name=~s/<\Q$TParams\E>\Z//;
4485 }
4486 else
4487 { # error
4488 $TParams = "";
4489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004490 return ($Name, $TParams);
4491}
4492
4493sub get_sub_ns($)
4494{
4495 my $Name = $_[0];
4496 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004497 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004498 {
4499 push(@NS, substr($Name, 0, $CPos));
4500 $Name = substr($Name, $CPos);
4501 $Name=~s/\A:://;
4502 }
4503 return (join("::", @NS), $Name);
4504}
4505
4506sub mangle_ns($$$)
4507{
4508 my ($Name, $LibVersion, $Repl) = @_;
4509 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4510 {
4511 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4512 $Mangled=~s/\AN(.+)E\Z/$1/;
4513 return $Mangled;
4514
4515 }
4516 else
4517 {
4518 my ($MangledNS, $SubNS) = ("", "");
4519 ($SubNS, $Name) = get_sub_ns($Name);
4520 if($SubNS) {
4521 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4522 }
4523 $MangledNS .= length($Name).$Name;
4524 add_substitution($MangledNS, $Repl, 0);
4525 return $MangledNS;
4526 }
4527}
4528
4529sub mangle_param($$$)
4530{
4531 my ($PTid, $LibVersion, $Repl) = @_;
4532 my ($MPrefix, $Mangled) = ("", "");
4533 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004534 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004535 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004536 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004537 if(not $BaseType_Name) {
4538 return "";
4539 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004540 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004541 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004542 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4543 while($Suffix=~/(&|\*|const)\Z/)
4544 {
4545 if($Suffix=~s/[ ]*&\Z//) {
4546 $MPrefix .= "R";
4547 }
4548 if($Suffix=~s/[ ]*\*\Z//) {
4549 $MPrefix .= "P";
4550 }
4551 if($Suffix=~s/[ ]*const\Z//)
4552 {
4553 if($MPrefix=~/R|P/
4554 or $Suffix=~/&|\*/) {
4555 $MPrefix .= "K";
4556 }
4557 }
4558 if($Suffix=~s/[ ]*volatile\Z//) {
4559 $MPrefix .= "V";
4560 }
4561 #if($Suffix=~s/[ ]*restrict\Z//) {
4562 #$MPrefix .= "r";
4563 #}
4564 }
4565 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4566 $Mangled .= $Token;
4567 }
4568 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4569 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004570 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004571 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004572 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004573 foreach (@TPos) {
4574 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004576 }
4577 elsif($TmplParams)
4578 { # remangling mode
4579 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004580 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 }
4582 my $MangledNS = "";
4583 my ($SubNS, $SName) = get_sub_ns($ShortName);
4584 if($SubNS) {
4585 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4586 }
4587 $MangledNS .= length($SName).$SName;
4588 if(@TParams) {
4589 add_substitution($MangledNS, $Repl, 0);
4590 }
4591 $Mangled .= "N".$MangledNS;
4592 if(@TParams)
4593 { # templates
4594 $Mangled .= "I";
4595 foreach my $TParam (@TParams) {
4596 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4597 }
4598 $Mangled .= "E";
4599 }
4600 $Mangled .= "E";
4601 }
4602 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4603 {
4604 if($BaseType{"Type"} eq "MethodPtr") {
4605 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4606 }
4607 else {
4608 $Mangled .= "PF";
4609 }
4610 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4611 my @Params = keys(%{$BaseType{"Param"}});
4612 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4613 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4614 }
4615 if(not @Params) {
4616 $Mangled .= "v";
4617 }
4618 $Mangled .= "E";
4619 }
4620 elsif($BaseType{"Type"} eq "FieldPtr")
4621 {
4622 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4623 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4624 }
4625 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4626 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4627 {
4628 if($Mangled eq $Optimized)
4629 {
4630 if($ShortName!~/::/)
4631 { # remove "N ... E"
4632 if($MPrefix) {
4633 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4634 }
4635 else {
4636 $Mangled=~s/\AN(.+)E\Z/$1/g;
4637 }
4638 }
4639 }
4640 else {
4641 $Mangled = $Optimized;
4642 }
4643 }
4644 add_substitution($Mangled, $Repl, 1);
4645 return $Mangled;
4646}
4647
4648sub mangle_template_param($$$)
4649{ # types + literals
4650 my ($TParam, $LibVersion, $Repl) = @_;
4651 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4652 return mangle_param($TPTid, $LibVersion, $Repl);
4653 }
4654 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4655 { # class_name<1u>::method(...)
4656 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4657 }
4658 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4659 { # class_name<(signed char)1>::method(...)
4660 return "L".$IntrinsicMangling{$1}.$2."E";
4661 }
4662 elsif($TParam eq "true")
4663 { # class_name<true>::method(...)
4664 return "Lb1E";
4665 }
4666 elsif($TParam eq "false")
4667 { # class_name<true>::method(...)
4668 return "Lb0E";
4669 }
4670 else { # internal error
4671 return length($TParam).$TParam;
4672 }
4673}
4674
4675sub add_substitution($$$)
4676{
4677 my ($Value, $Repl, $Rec) = @_;
4678 if($Rec)
4679 { # subtypes
4680 my @Subs = ($Value);
4681 while($Value=~s/\A(R|P|K)//) {
4682 push(@Subs, $Value);
4683 }
4684 foreach (reverse(@Subs)) {
4685 add_substitution($_, $Repl, 0);
4686 }
4687 return;
4688 }
4689 return if($Value=~/\AS(\d*)_\Z/);
4690 $Value=~s/\AN(.+)E\Z/$1/g;
4691 return if(defined $Repl->{$Value});
4692 return if(length($Value)<=1);
4693 return if($StdcxxMangling{$Value});
4694 # check for duplicates
4695 my $Base = $Value;
4696 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4697 {
4698 my $Num = $Repl->{$Type};
4699 my $Replace = macro_mangle($Num);
4700 $Base=~s/\Q$Replace\E/$Type/;
4701 }
4702 if(my $OldNum = $Repl->{$Base})
4703 {
4704 $Repl->{$Value} = $OldNum;
4705 return;
4706 }
4707 my @Repls = sort {$b<=>$a} values(%{$Repl});
4708 if(@Repls) {
4709 $Repl->{$Value} = $Repls[0]+1;
4710 }
4711 else {
4712 $Repl->{$Value} = -1;
4713 }
4714 # register duplicates
4715 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004716 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004717 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4718 {
4719 next if($Base eq $Type);
4720 my $Num = $Repl->{$Type};
4721 my $Replace = macro_mangle($Num);
4722 $Base=~s/\Q$Type\E/$Replace/;
4723 $Repl->{$Base} = $Repl->{$Value};
4724 }
4725}
4726
4727sub macro_mangle($)
4728{
4729 my $Num = $_[0];
4730 if($Num==-1) {
4731 return "S_";
4732 }
4733 else
4734 {
4735 my $Code = "";
4736 if($Num<10)
4737 { # S0_, S1_, S2_, ...
4738 $Code = $Num;
4739 }
4740 elsif($Num>=10 and $Num<=35)
4741 { # SA_, SB_, SC_, ...
4742 $Code = chr(55+$Num);
4743 }
4744 else
4745 { # S10_, S11_, S12_
4746 $Code = $Num-26; # 26 is length of english alphabet
4747 }
4748 return "S".$Code."_";
4749 }
4750}
4751
4752sub write_stdcxx_substitution($)
4753{
4754 my $Mangled = $_[0];
4755 if($StdcxxMangling{$Mangled}) {
4756 return $StdcxxMangling{$Mangled};
4757 }
4758 else
4759 {
4760 my @Repls = keys(%StdcxxMangling);
4761 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4762 foreach my $MangledType (@Repls)
4763 {
4764 my $Replace = $StdcxxMangling{$MangledType};
4765 #if($Mangled!~/$Replace/) {
4766 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4767 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4768 #}
4769 }
4770 }
4771 return $Mangled;
4772}
4773
4774sub write_substitution($$)
4775{
4776 my ($Mangled, $Repl) = @_;
4777 if(defined $Repl->{$Mangled}
4778 and my $MnglNum = $Repl->{$Mangled}) {
4779 $Mangled = macro_mangle($MnglNum);
4780 }
4781 else
4782 {
4783 my @Repls = keys(%{$Repl});
4784 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4785 # FIXME: how to apply replacements? by num or by pos
4786 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4787 foreach my $MangledType (@Repls)
4788 {
4789 my $Replace = macro_mangle($Repl->{$MangledType});
4790 if($Mangled!~/$Replace/) {
4791 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4792 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4793 }
4794 }
4795 }
4796 return $Mangled;
4797}
4798
4799sub delete_keywords($)
4800{
4801 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004802 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004803 return $TypeName;
4804}
4805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004806sub uncover_typedefs($$)
4807{
4808 my ($TypeName, $LibVersion) = @_;
4809 return "" if(not $TypeName);
4810 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4811 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4812 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004813 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004814 while($TypeName_New ne $TypeName_Pre)
4815 {
4816 $TypeName_Pre = $TypeName_New;
4817 my $TypeName_Copy = $TypeName_New;
4818 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004819 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004820 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004821 if(not $Intrinsic_Keywords{$1}) {
4822 $Words{$1} = 1;
4823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004824 }
4825 foreach my $Word (keys(%Words))
4826 {
4827 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4828 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004829 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004830 if($BaseType_Name=~/\([\*]+\)/)
4831 { # FuncPtr
4832 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4833 {
4834 my $Type_Suffix = $1;
4835 $TypeName_New = $BaseType_Name;
4836 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004837 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004838 }
4839 }
4840 }
4841 else
4842 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004843 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004844 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004845 }
4846 }
4847 }
4848 }
4849 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4850}
4851
4852sub isInternal($)
4853{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004854 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4855 {
4856 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4857 {
4858 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4859 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4860 return 1;
4861 }
4862 }
4863 }
4864 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004865}
4866
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004867sub getDataVal($$)
4868{
4869 my ($InfoId, $TypeId) = @_;
4870 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4871 {
4872 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4873 {
4874 if(defined $LibInfo{$Version}{"info_type"}{$1}
4875 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004876 {
4877 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004878 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004879 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4880 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004881 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004882 if(my $Addr = getTreeAttr_Op($1)) {
4883 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004884 }
4885 }
4886 }
4887 }
4888 else {
4889 return getInitVal($1, $TypeId);
4890 }
4891 }
4892 }
4893 return undef;
4894}
4895
4896sub getInitVal($$)
4897{
4898 my ($InfoId, $TypeId) = @_;
4899 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4900 {
4901 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4902 {
4903 if($InfoType eq "integer_cst")
4904 {
4905 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004906 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004907 { # characters
4908 $Val = chr($Val);
4909 }
4910 return $Val;
4911 }
4912 elsif($InfoType eq "string_cst") {
4913 return getNodeStrCst($InfoId);
4914 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004915 elsif($InfoType eq "var_decl")
4916 {
4917 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4918 return $Name;
4919 }
4920 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004921 }
4922 }
4923 return undef;
4924}
4925
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004926sub set_Class_And_Namespace($)
4927{
4928 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004929 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004931 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004932 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004933 my $NSInfoId = $1;
4934 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4935 {
4936 if($InfoType eq "namespace_decl") {
4937 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4938 }
4939 elsif($InfoType eq "record_type") {
4940 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4941 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004943 }
4944 }
4945 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4946 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004947 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004948 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004949 { # skip
4950 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004952 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004953
4954 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004955}
4956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004957sub debugMangling($)
4958{
4959 my $LibVersion = $_[0];
4960 my %Mangled = ();
4961 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4962 {
4963 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4964 {
4965 if($Mngl=~/\A(_Z|\?)/) {
4966 $Mangled{$Mngl}=$InfoId;
4967 }
4968 }
4969 }
4970 translateSymbols(keys(%Mangled), $LibVersion);
4971 foreach my $Mngl (keys(%Mangled))
4972 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004973 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4974 my $U2 = $tr_name{$Mngl};
4975 if($U1 ne $U2) {
4976 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004977 }
4978 }
4979}
4980
4981sub linkSymbol($)
4982{ # link symbols from shared libraries
4983 # with the symbols from header files
4984 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004985 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004986 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004987 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4988 or $EMERGENCY_MODE_48)
4989 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4990 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03004991 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004992 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004993 {
4994 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4995 return correct_incharge($InfoId, $Version, $Mangled);
4996 }
4997 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004998 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004999 or not $BinaryOnly
5000 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005001 { # 1. --headers-only mode
5002 # 2. not mangled src-only symbols
5003 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5004 return $Mangled;
5005 }
5006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 }
5008 return "";
5009}
5010
5011sub setLanguage($$)
5012{
5013 my ($LibVersion, $Lang) = @_;
5014 if(not $UserLang) {
5015 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5016 }
5017}
5018
5019sub getSymbolInfo($)
5020{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005021 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005022 if(isInternal($InfoId)) {
5023 return;
5024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005025 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5026 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005027 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005029 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005030 return;
5031 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005032 setFuncAccess($InfoId);
5033 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005034 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5035 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005036 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005037 return;
5038 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005039
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005040 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005041 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005042 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005043 if(not defined $TypeInfo{$Version}{$Return}
5044 or not $TypeInfo{$Version}{$Return}{"Name"})
5045 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005046 delete($SymbolInfo{$Version}{$InfoId});
5047 return;
5048 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005049 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005050 }
5051 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5052 {
5053 if(defined $MissedTypedef{$Version}{$Rid})
5054 {
5055 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5056 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5057 }
5058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005060 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5061 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005062 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005063 my $Orig = getFuncOrig($InfoId);
5064 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005065 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5066 {
5067 delete($SymbolInfo{$Version}{$InfoId});
5068 return;
5069 }
5070
5071 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005073 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 return;
5075 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005076
5077 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005078 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005079 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5080
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005081 my @TParams = getTParams($Orig, "Func");
5082 if(not @TParams)
5083 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005084 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 return;
5086 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005087 foreach my $Pos (0 .. $#TParams)
5088 {
5089 my $Val = $TParams[$Pos];
5090 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5091
5092 if($Tmpl)
5093 {
5094 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5095 {
5096 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5097 }
5098 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005099 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005100
5101 if($Tmpl)
5102 {
5103 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5104 {
5105 if($Pos>$#TParams)
5106 {
5107 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5108 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5109 }
5110 }
5111 }
5112
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005113 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5114 { # operator<< <T>, operator>> <T>
5115 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5116 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005117 if(@TParams) {
5118 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5119 }
5120 else {
5121 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5122 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005123 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 }
5125 else
5126 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005129 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5130 {
5131 if($OSgroup eq "windows")
5132 { # cut the offset
5133 $MnglName=~s/\@\d+\Z//g;
5134 }
5135 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5136
5137 # NOTE: mangling of some symbols may change depending on GCC version
5138 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5139 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5140 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005141
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005142 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005143 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005145 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 return;
5147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005148 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005149 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005150 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005151 if($Skip)
5152 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005153 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005154 return;
5155 }
5156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005157 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5158 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5159 }
5160
5161 if(set_Class_And_Namespace($InfoId))
5162 {
5163 delete($SymbolInfo{$Version}{$InfoId});
5164 return;
5165 }
5166
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005167 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5168 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005169 if(not defined $TypeInfo{$Version}{$ClassId}
5170 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005172 delete($SymbolInfo{$Version}{$InfoId});
5173 return;
5174 }
5175 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005176 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5177 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005178 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005179 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005180 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005181 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005182 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005184 }
5185 if($COMMON_LANGUAGE{$Version} eq "C++")
5186 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005187 # C++ or --headers-only mode
5188 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005189 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005190 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5191 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005193 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005194 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005195 if(my $Mangled = linkSymbol($InfoId)) {
5196 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005197 }
5198 }
5199 if($OStarget eq "windows")
5200 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005201 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005203 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005205 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005206 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005207 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005208 }
5209 }
5210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005211 else
5212 { # not mangled in C
5213 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5214 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005215 if(not $CheckHeadersOnly
5216 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5217 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5218 {
5219 my $Incorrect = 0;
5220
5221 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5222 {
5223 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5224 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5225 { # mangled in the TU dump, but not mangled in the library
5226 $Incorrect = 1;
5227 }
5228 }
5229 else
5230 {
5231 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5232 { # all C++ functions are not mangled in the TU dump
5233 $Incorrect = 1;
5234 }
5235 }
5236 if($Incorrect)
5237 {
5238 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5239 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5240 }
5241 }
5242 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 return;
5247 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005248 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005249 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005250 { # identify virtual and pure virtual functions
5251 # NOTE: constructors cannot be virtual
5252 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5253 # in the TU dump, so taking it from the original symbol
5254 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5255 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5256 { # NOTE: D2 destructors are not present in a v-table
5257 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 if(isInline($InfoId)) {
5261 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005263 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005264 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5267 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005270 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005271 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005272 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 }
5274 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005275 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5276 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005277 if(not $ExtraDump)
5278 {
5279 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5280 { # non-target symbols
5281 delete($SymbolInfo{$Version}{$InfoId});
5282 return;
5283 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005286 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5287 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5288 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5289 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005291 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5292 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 return;
5295 }
5296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005300 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005301 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 return;
5303 }
5304 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 }
5307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5309 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5310 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005312 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5313 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005314 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005315 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005317 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 }
5319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005320 if(getFuncLink($InfoId) eq "Static") {
5321 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005322 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005323 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5324 {
5325 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005327 if($Unmangled=~/\.\_\d/)
5328 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005329 delete($SymbolInfo{$Version}{$InfoId});
5330 return;
5331 }
5332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005334
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005335 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5336 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005338 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5339 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005341
5342 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5343 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5344 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005345
5346 if($ExtraDump) {
5347 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5348 }
5349}
5350
5351sub guessHeader($)
5352{
5353 my $InfoId = $_[0];
5354 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5355 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5356 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5357 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5358 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5359 {
5360 if(get_filename($HPath) eq $Header)
5361 {
5362 my $HDir = get_filename(get_dirname($HPath));
5363 if($HDir ne "include"
5364 and $HDir=~/\A[a-z]+\Z/i) {
5365 return join_P($HDir, $Header);
5366 }
5367 }
5368 }
5369 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005370}
5371
5372sub isInline($)
5373{ # "body: undefined" in the tree
5374 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005375 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5376 {
5377 if($Info=~/ undefined /i) {
5378 return 0;
5379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 }
5381 return 1;
5382}
5383
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005384sub hasThrow($)
5385{
5386 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5387 {
5388 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5389 return getTreeAttr_Unql($1, "unql");
5390 }
5391 }
5392 return 1;
5393}
5394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395sub getTypeId($)
5396{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005397 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5398 {
5399 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5400 return $1;
5401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005403 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404}
5405
5406sub setTypeMemb($$)
5407{
5408 my ($TypeId, $TypeAttr) = @_;
5409 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005410 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005411 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 if($TypeType eq "Enum")
5413 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 my $MInfoId = getTreeAttr_Csts($TypeId);
5415 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005417 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5418 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005419 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005420 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5421 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005422 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005423 }
5424 }
5425 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5426 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005427 my $MInfoId = getTreeAttr_Flds($TypeId);
5428 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005429 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005430 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5431 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005432 if(not $IType or $IType ne "field_decl")
5433 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005434
5435 if($IType eq "var_decl")
5436 { # static field
5437 $StaticFields = 1;
5438 }
5439
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005440 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 next;
5442 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005443 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005444 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005445 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005446 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 }
5448 if(not $StructMembName)
5449 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005450 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005452 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5454 if(isAnon($UnnamedTName))
5455 { # rename unnamed fields to unnamed0, unnamed1, ...
5456 $StructMembName = "unnamed".($UnnamedPos++);
5457 }
5458 }
5459 }
5460 if(not $StructMembName)
5461 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005462 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005463 next;
5464 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005466 if(defined $MissedTypedef{$Version}{$MembTypeId})
5467 {
5468 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5469 $MembTypeId = $AddedTid;
5470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005472
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005473 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5474 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005475 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005476 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005477 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5478 }
5479 if($MInfo=~/spec:\s*mutable /)
5480 { # mutable fields
5481 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005483 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005484 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5485 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005486 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005487 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005488 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 }
5490 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005491 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005492 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5493 { # template
5494 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5495 }
5496 else {
5497 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005500
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005501 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005502 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005503 }
5504 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005505
5506 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507}
5508
5509sub setFuncParams($)
5510{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005511 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005512 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005513
5514 my $FType = getFuncType($InfoId);
5515
5516 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005518 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5519 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005520 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005521 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005522 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005524 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005525 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005528 else
5529 { # skip
5530 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005532 # skip "this"-parameter
5533 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005534 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005535 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005538 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5539 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5540 if(not $ParamName)
5541 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005542 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005544 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5545 {
5546 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5547 $ParamTypeId = $AddedTid;
5548 }
5549 }
5550 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 if(not $PType or $PType eq "Unknown") {
5552 return 1;
5553 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005554 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005555 if(not $PTName) {
5556 return 1;
5557 }
5558 if($PTName eq "void") {
5559 last;
5560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005562 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005564 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 $ParamInfoId = getNextElem($ParamInfoId);
5566 next;
5567 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005568 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005569
5570 if(my %Base = get_BaseType($ParamTypeId, $Version))
5571 {
5572 if(defined $Base{"Template"}) {
5573 return 1;
5574 }
5575 }
5576
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005577 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005578 if(my $Algn = getAlgn($ParamInfoId)) {
5579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005581 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5582 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005584 }
5585 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005587 if($ParamName ne "this" or $FType ne "Method") {
5588 $PPos += 1;
5589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005590 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005591 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005592 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005593 }
5594 return 0;
5595}
5596
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005597sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005598{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005599 my ($InfoId, $Vtt_Pos) = @_;
5600 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005601 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005602 my $FType = getFuncType($InfoId);
5603
5604 if($FType eq "Method")
5605 {
5606 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005607 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 if(not $ParamListElemId)
5610 { # foo(...)
5611 return 1;
5612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005614 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005616 { # actual params: may differ from formal args
5617 # formal int*const
5618 # actual: int*
5619 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620 {
5621 $Vtt_Pos=-1;
5622 $ParamListElemId = getNextElem($ParamListElemId);
5623 next;
5624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005625 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5626 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005627 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 $HaveVoid = 1;
5629 last;
5630 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005631 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005633 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5634 {
5635 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5636 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5637 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005638 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005639 }
5640 }
5641 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5642 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005643 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005644 { # params
5645 if($OldId ne $ParamTypeId)
5646 {
5647 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5648 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5649
5650 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5651 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5652 }
5653 }
5654 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005655 }
5656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005657 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005658 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005659 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5660 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005661 if($PurpType eq "nop_expr")
5662 { # func ( const char* arg = (const char*)(void*)0 )
5663 $PurpId = getTreeAttr_Op($PurpId);
5664 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005665 my $Val = getInitVal($PurpId, $ParamTypeId);
5666 if(defined $Val) {
5667 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005669 }
5670 }
5671 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005672 if($Pos!=0 or $FType ne "Method") {
5673 $PPos += 1;
5674 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005675 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005676 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005677 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005678}
5679
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005680sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005681{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005682 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005684 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5685 return $1;
5686 }
5687 }
5688 return "";
5689}
5690
5691sub getTreeAttr_Chain($)
5692{
5693 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5694 {
5695 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5696 return $1;
5697 }
5698 }
5699 return "";
5700}
5701
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005702sub getTreeAttr_Unql($)
5703{
5704 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5705 {
5706 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5707 return $1;
5708 }
5709 }
5710 return "";
5711}
5712
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005713sub getTreeAttr_Scpe($)
5714{
5715 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5716 {
5717 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5718 return $1;
5719 }
5720 }
5721 return "";
5722}
5723
5724sub getTreeAttr_Type($)
5725{
5726 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5727 {
5728 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5729 return $1;
5730 }
5731 }
5732 return "";
5733}
5734
5735sub getTreeAttr_Name($)
5736{
5737 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5738 {
5739 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5740 return $1;
5741 }
5742 }
5743 return "";
5744}
5745
5746sub getTreeAttr_Mngl($)
5747{
5748 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5749 {
5750 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5751 return $1;
5752 }
5753 }
5754 return "";
5755}
5756
5757sub getTreeAttr_Prms($)
5758{
5759 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5760 {
5761 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5762 return $1;
5763 }
5764 }
5765 return "";
5766}
5767
5768sub getTreeAttr_Fncs($)
5769{
5770 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5771 {
5772 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5773 return $1;
5774 }
5775 }
5776 return "";
5777}
5778
5779sub getTreeAttr_Csts($)
5780{
5781 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5782 {
5783 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5784 return $1;
5785 }
5786 }
5787 return "";
5788}
5789
5790sub getTreeAttr_Purp($)
5791{
5792 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5793 {
5794 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5795 return $1;
5796 }
5797 }
5798 return "";
5799}
5800
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005801sub getTreeAttr_Op($)
5802{
5803 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5804 {
5805 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5806 return $1;
5807 }
5808 }
5809 return "";
5810}
5811
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005812sub getTreeAttr_Valu($)
5813{
5814 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5815 {
5816 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5817 return $1;
5818 }
5819 }
5820 return "";
5821}
5822
5823sub getTreeAttr_Flds($)
5824{
5825 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5826 {
5827 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5828 return $1;
5829 }
5830 }
5831 return "";
5832}
5833
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005834sub getTreeAttr_Binf($)
5835{
5836 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5837 {
5838 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5839 return $1;
5840 }
5841 }
5842 return "";
5843}
5844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005845sub getTreeAttr_Args($)
5846{
5847 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5848 {
5849 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005850 return $1;
5851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005852 }
5853 return "";
5854}
5855
5856sub getTreeValue($)
5857{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005858 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5859 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005860 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5861 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005863 }
5864 return "";
5865}
5866
5867sub getTreeAccess($)
5868{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005869 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005870 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005871 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5872 {
5873 my $Access = $1;
5874 if($Access eq "prot") {
5875 return "protected";
5876 }
5877 elsif($Access eq "priv") {
5878 return "private";
5879 }
5880 }
5881 elsif($Info=~/ protected /)
5882 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883 return "protected";
5884 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005885 elsif($Info=~/ private /)
5886 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887 return "private";
5888 }
5889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005890 return "public";
5891}
5892
5893sub setFuncAccess($)
5894{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005895 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005896 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005897 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005898 }
5899 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005900 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005901 }
5902}
5903
5904sub setTypeAccess($$)
5905{
5906 my ($TypeId, $TypeAttr) = @_;
5907 my $Access = getTreeAccess($TypeId);
5908 if($Access eq "protected") {
5909 $TypeAttr->{"Protected"} = 1;
5910 }
5911 elsif($Access eq "private") {
5912 $TypeAttr->{"Private"} = 1;
5913 }
5914}
5915
5916sub setFuncKind($)
5917{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005918 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5919 {
5920 if($Info=~/pseudo tmpl/) {
5921 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5922 }
5923 elsif($Info=~/ constructor /) {
5924 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5925 }
5926 elsif($Info=~/ destructor /) {
5927 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 }
5930}
5931
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005932sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005934 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5935 {
5936 if($Info=~/spec[ ]*:[ ]*pure /) {
5937 return "PureVirt";
5938 }
5939 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5940 return "Virt";
5941 }
5942 elsif($Info=~/ pure\s+virtual /)
5943 { # support for old GCC versions
5944 return "PureVirt";
5945 }
5946 elsif($Info=~/ virtual /)
5947 { # support for old GCC versions
5948 return "Virt";
5949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950 }
5951 return "";
5952}
5953
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954sub getFuncLink($)
5955{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005956 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5957 {
5958 if($Info=~/link[ ]*:[ ]*static /) {
5959 return "Static";
5960 }
5961 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 return $1;
5963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005964 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005965 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966}
5967
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005970 my ($Symbol, $LibVersion) = @_;
5971 return "" if(not $Symbol or not $LibVersion);
5972 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5973 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005974 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005975 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5976 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5977 }
5978 }
5979 if($NS)
5980 {
5981 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5982 return $NS;
5983 }
5984 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005986 while($NS=~s/::[^:]+\Z//)
5987 {
5988 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5989 return $NS;
5990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991 }
5992 }
5993 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005994
5995 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996}
5997
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005998sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999{
6000 my ($TypeName, $LibVersion) = @_;
6001 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006002 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006004 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6005 return $NS;
6006 }
6007 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006009 while($NS=~s/::[^:]+\Z//)
6010 {
6011 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6012 return $NS;
6013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 }
6015 }
6016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006017 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018}
6019
6020sub getNameSpace($)
6021{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006022 my $InfoId = $_[0];
6023 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006025 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006027 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006029 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6030 {
6031 my $NameSpace = getTreeStr($1);
6032 if($NameSpace eq "::")
6033 { # global namespace
6034 return "";
6035 }
6036 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6037 $NameSpace = $BaseNameSpace."::".$NameSpace;
6038 }
6039 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6040 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006042 else {
6043 return "";
6044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006045 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006046 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006047 { # inside data type
6048 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6049 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006053 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054}
6055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006056sub getEnumMembVal($)
6057{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006058 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006060 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6061 {
6062 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6063 {
6064 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6065 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6066 return getTreeValue($1);
6067 }
6068 else
6069 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6070 return getTreeValue($1);
6071 }
6072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006073 }
6074 }
6075 return "";
6076}
6077
6078sub getSize($)
6079{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006080 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6081 {
6082 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6083 return getTreeValue($1);
6084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006086 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006087}
6088
6089sub getAlgn($)
6090{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006091 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6092 {
6093 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6094 return $1;
6095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006097 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006098}
6099
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006100sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006101{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006102 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6103 {
6104 if($Info=~/ bitfield /) {
6105 return getSize($_[0]);
6106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006107 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006108 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006109}
6110
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006111sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006112{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006113 if(my $Chan = getTreeAttr_Chan($_[0])) {
6114 return $Chan;
6115 }
6116 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6117 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006118 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006119 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120}
6121
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006122sub registerHeader($$)
6123{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 return "";
6127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006128 if(is_abs($Header) and not -f $Header)
6129 { # incorrect absolute path
6130 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132 if(skipHeader($Header, $LibVersion))
6133 { # skip
6134 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006136 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6137 {
6138 detect_header_includes($Header_Path, $LibVersion);
6139
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006140 if(defined $Tolerance and $Tolerance=~/3/)
6141 { # 3 - skip headers that include non-Linux headers
6142 if($OSgroup ne "windows")
6143 {
6144 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6145 {
6146 if(specificHeader($Inc, "windows")) {
6147 return "";
6148 }
6149 }
6150 }
6151 }
6152
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006153 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6154 { # redirect
6155 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6156 or skipHeader($RHeader_Path, $LibVersion))
6157 { # skip
6158 return "";
6159 }
6160 $Header_Path = $RHeader_Path;
6161 }
6162 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6163 { # skip
6164 return "";
6165 }
6166
6167 if(my $HName = get_filename($Header_Path))
6168 { # register
6169 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6170 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6171 }
6172
6173 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6174 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006175 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006176 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006177 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006178 }
6179
6180 if($CheckHeadersOnly
6181 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6182 { # /usr/include/c++/4.6.1/...
6183 $STDCXX_TESTING = 1;
6184 }
6185
6186 return $Header_Path;
6187 }
6188 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189}
6190
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006191sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192{
6193 my ($Dir, $WithDeps, $LibVersion) = @_;
6194 $Dir=~s/[\/\\]+\Z//g;
6195 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006198 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006199 if($WithDeps)
6200 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6202 return;
6203 }
6204 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6205 $Mode = "DepsOnly";
6206 }
6207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006208 else
6209 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6211 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6212 return;
6213 }
6214 }
6215 $Header_Dependency{$LibVersion}{$Dir} = 1;
6216 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6217 if($Mode eq "DepsOnly")
6218 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006219 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 $Header_Dependency{$LibVersion}{$Path} = 1;
6221 }
6222 return;
6223 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006224 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 {
6226 if($WithDeps)
6227 {
6228 my $SubDir = $Path;
6229 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6230 { # register all sub directories
6231 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6232 }
6233 }
6234 next if(is_not_header($Path));
6235 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006237 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006238 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6239 }
6240 }
6241 if(get_filename($Dir) eq "include")
6242 { # search for "lib/include/" directory
6243 my $LibDir = $Dir;
6244 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006245 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006246 }
6247 }
6248}
6249
6250sub parse_redirect($$$)
6251{
6252 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006253 my @Errors = ();
6254 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6255 push(@Errors, $1);
6256 }
6257 my $Redirect = "";
6258 foreach (@Errors)
6259 {
6260 s/\s{2,}/ /g;
6261 if(/(only|must\ include
6262 |update\ to\ include
6263 |replaced\ with
6264 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006265 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 {
6267 $Redirect = $2;
6268 last;
6269 }
6270 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6271 {
6272 $Redirect = $2;
6273 last;
6274 }
6275 elsif(/this\ header\ should\ not\ be\ used
6276 |programs\ should\ not\ directly\ include
6277 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6278 |is\ not\ supported\ API\ for\ general\ use
6279 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006280 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6282 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6283 }
6284 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006285 if($Redirect)
6286 {
6287 $Redirect=~s/\A<//g;
6288 $Redirect=~s/>\Z//g;
6289 }
6290 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006291}
6292
6293sub parse_includes($$)
6294{
6295 my ($Content, $Path) = @_;
6296 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006297 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006298 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006299 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006300 my $Method = substr($Header, 0, 1, "");
6301 substr($Header, length($Header)-1, 1, "");
6302 $Header = path_format($Header, $OSgroup);
6303 if($Method eq "\"" or is_abs($Header))
6304 {
6305 if(-e join_P(get_dirname($Path), $Header))
6306 { # relative path exists
6307 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006309 else
6310 { # include "..." that doesn't exist is equal to include <...>
6311 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006313 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006314 else {
6315 $Includes{$Header} = 1;
6316 }
6317 }
6318 if($ExtraInfo)
6319 {
6320 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6321 { # FT_FREETYPE_H
6322 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 }
6324 }
6325 return \%Includes;
6326}
6327
6328sub ignore_path($)
6329{
6330 my $Path = $_[0];
6331 if($Path=~/\~\Z/)
6332 {# skipping system backup files
6333 return 1;
6334 }
6335 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6336 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6337 return 1;
6338 }
6339 return 0;
6340}
6341
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006342sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343{
6344 my ($ArrRef, $W) = @_;
6345 return if(length($W)<2);
6346 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6347}
6348
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006349sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350{
6351 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 $H1=~s/\.[a-z]+\Z//ig;
6354 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006355
6356 my $Hname1 = get_filename($H1);
6357 my $Hname2 = get_filename($H2);
6358 my $HDir1 = get_dirname($H1);
6359 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006360 my $Dirname1 = get_filename($HDir1);
6361 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006362
6363 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6364 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6365
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006366 if($_[0] eq $_[1]
6367 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 return 0;
6369 }
6370 elsif($H1=~/\A\Q$H2\E/) {
6371 return 1;
6372 }
6373 elsif($H2=~/\A\Q$H1\E/) {
6374 return -1;
6375 }
6376 elsif($HDir1=~/\Q$Hname1\E/i
6377 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006378 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 return -1;
6380 }
6381 elsif($HDir2=~/\Q$Hname2\E/i
6382 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006383 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006384 return 1;
6385 }
6386 elsif($Hname1=~/\Q$Dirname1\E/i
6387 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006388 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006389 return -1;
6390 }
6391 elsif($Hname2=~/\Q$Dirname2\E/i
6392 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006393 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006394 return 1;
6395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006396 elsif($Hname1=~/(config|lib|util)/i
6397 and $Hname2!~/(config|lib|util)/i)
6398 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 return -1;
6400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006401 elsif($Hname2=~/(config|lib|util)/i
6402 and $Hname1!~/(config|lib|util)/i)
6403 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 return 1;
6405 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006406 else
6407 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006408 my $R1 = checkRelevance($H1);
6409 my $R2 = checkRelevance($H2);
6410 if($R1 and not $R2)
6411 { # libebook/e-book.h
6412 return -1;
6413 }
6414 elsif($R2 and not $R1)
6415 { # libebook/e-book.h
6416 return 1;
6417 }
6418 else
6419 {
6420 return (lc($H1) cmp lc($H2));
6421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 }
6423}
6424
6425sub searchForHeaders($)
6426{
6427 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006429 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006430 registerGccHeaders();
6431
6432 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6433 { # c++ standard include paths
6434 registerCppHeaders();
6435 }
6436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006438 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6439 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006440 {
6441 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006442 if($SystemRoot)
6443 {
6444 if(is_abs($Path)) {
6445 $Path = $SystemRoot.$Path;
6446 }
6447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006448 if(not -e $Path) {
6449 exitStatus("Access_Error", "can't access \'$Path\'");
6450 }
6451 elsif(-f $Path) {
6452 exitStatus("Access_Error", "\'$Path\' - not a directory");
6453 }
6454 elsif(-d $Path)
6455 {
6456 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006457 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006458 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6459 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 }
6461 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006462 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 }
6464 }
6465 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006466 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006467 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6468 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 # registering directories
6471 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6472 {
6473 next if(not -e $Path);
6474 $Path = get_abs_path($Path);
6475 $Path = path_format($Path, $OSgroup);
6476 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006477 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006478 }
6479 elsif(-f $Path)
6480 {
6481 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006482 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006483 and not $LocalIncludes{$Dir})
6484 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006486 # if(my $OutDir = get_dirname($Dir))
6487 # { # registering the outer directory
6488 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6489 # and not $LocalIncludes{$OutDir}) {
6490 # registerDir($OutDir, 0, $LibVersion);
6491 # }
6492 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 }
6494 }
6495 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006496
6497 # clean memory
6498 %RegisteredDirs = ();
6499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006500 # registering headers
6501 my $Position = 0;
6502 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6503 {
6504 if(is_abs($Dest) and not -e $Dest) {
6505 exitStatus("Access_Error", "can't access \'$Dest\'");
6506 }
6507 $Dest = path_format($Dest, $OSgroup);
6508 if(is_header($Dest, 1, $LibVersion))
6509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006510 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6512 }
6513 }
6514 elsif(-d $Dest)
6515 {
6516 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006517 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006518 {
6519 next if(ignore_path($Path));
6520 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006521 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 push(@Registered, $HPath);
6523 }
6524 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006525 @Registered = sort {sortHeaders($a, $b)} @Registered;
6526 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006527 foreach my $Path (@Registered) {
6528 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6529 }
6530 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006531 elsif(not defined $SkipUnidentified) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6533 }
6534 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006535
6536 if(defined $Tolerance and $Tolerance=~/4/)
6537 { # 4 - skip headers included by others
6538 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6539 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006540 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006541 delete($Registered_Headers{$LibVersion}{$Path});
6542 }
6543 }
6544 }
6545
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006546 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6547 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006548 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006549 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006550 if(is_abs($Header) and not -f $Header) {
6551 exitStatus("Access_Error", "can't access file \'$Header\'");
6552 }
6553 $Header = path_format($Header, $OSgroup);
6554 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006556 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006557 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006558 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006559 elsif($SkipUnidentified) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006560 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006562 }
6563 }
6564 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6565 { # set relative paths (for duplicates)
6566 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6567 { # search for duplicates
6568 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6569 my $Prefix = get_dirname($FirstPath);
6570 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6571 { # detect a shortest distinguishing prefix
6572 my $NewPrefix = $1;
6573 my %Identity = ();
6574 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6575 {
6576 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6577 $Identity{$Path} = $1;
6578 }
6579 }
6580 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006581 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006582 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6583 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6584 }
6585 last;
6586 }
6587 $Prefix = $NewPrefix; # increase prefix
6588 }
6589 }
6590 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006591
6592 # clean memory
6593 %HeaderName_Paths = ();
6594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006595 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6596 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006597 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006598 my ($Pos, $PairPos) = (-1, -1);
6599 my ($Path, $PairPath) = ();
6600 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6601 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6602 foreach my $Header_Path (@Paths)
6603 {
6604 if(get_filename($Header_Path) eq $PairName)
6605 {
6606 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6607 $PairPath = $Header_Path;
6608 }
6609 if(get_filename($Header_Path) eq $HeaderName)
6610 {
6611 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6612 $Path = $Header_Path;
6613 }
6614 }
6615 if($PairPos!=-1 and $Pos!=-1
6616 and int($PairPos)<int($Pos))
6617 {
6618 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6619 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6620 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6621 }
6622 }
6623 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6624 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6625 }
6626}
6627
6628sub detect_real_includes($$)
6629{
6630 my ($AbsPath, $LibVersion) = @_;
6631 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6632 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6633 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6634 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6635 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006636 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006638 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6639 return () if(not $Path);
6640 open(PREPROC, $Path);
6641 while(<PREPROC>)
6642 {
6643 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6644 {
6645 my $Include = path_format($1, $OSgroup);
6646 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6647 next;
6648 }
6649 if($Include eq $AbsPath) {
6650 next;
6651 }
6652 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6653 }
6654 }
6655 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006656 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6657}
6658
6659sub detect_header_includes($$)
6660{
6661 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006662 return if(not $LibVersion or not $Path);
6663 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6664 return;
6665 }
6666 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6667
6668 if(not -e $Path) {
6669 return;
6670 }
6671
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006673 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6674 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006675 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006676 {
6677 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006678 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006679 }
6680 if($RedirectPath ne $Path) {
6681 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6682 }
6683 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006684 else
6685 { # can't find
6686 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006688 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006689 if(my $Inc = parse_includes($Content, $Path))
6690 {
6691 foreach my $Include (keys(%{$Inc}))
6692 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006693 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006694
6695 if(defined $Tolerance and $Tolerance=~/4/)
6696 {
6697 if(my $HPath = identifyHeader($Include, $LibVersion))
6698 {
6699 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6700 }
6701 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704}
6705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006706sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006707{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 my $Path = $_[0];
6709 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006710 if($OStarget eq "symbian")
6711 {
6712 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6713 { # epoc32/include/libc/{stdio, ...}.h
6714 return 1;
6715 }
6716 }
6717 else
6718 {
6719 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6720 { # /usr/include/{stdio, ...}.h
6721 return 1;
6722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724 return 0;
6725}
6726
6727sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006728{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 my $Dir = $_[0];
6730 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006731 if($OStarget eq "symbian")
6732 {
6733 if(get_filename($OutDir) eq "libc"
6734 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6735 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6736 return 1;
6737 }
6738 }
6739 else
6740 { # linux
6741 if($OutDir eq "/usr/include"
6742 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6743 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6744 return 1;
6745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006746 }
6747 return 0;
6748}
6749
6750sub detect_recursive_includes($$)
6751{
6752 my ($AbsPath, $LibVersion) = @_;
6753 return () if(not $AbsPath);
6754 if(isCyclical(\@RecurInclude, $AbsPath)) {
6755 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6756 }
6757 my ($AbsDir, $Name) = separate_path($AbsPath);
6758 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006759 { # system GLIBC internals
6760 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006761 }
6762 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6763 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6764 }
6765 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006766
6767 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6768 { # skip /usr/include/c++/*/ headers
6769 return () if(not $ExtraInfo);
6770 }
6771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006773 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006774 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 { # check "real" (non-"model") include paths
6776 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6777 pop(@RecurInclude);
6778 return @Paths;
6779 }
6780 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6781 detect_header_includes($AbsPath, $LibVersion);
6782 }
6783 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6784 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006785 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006787 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006789 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006790 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006791 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006792 }
6793 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006794 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006795 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006796 { # search for the nearest header
6797 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006798 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006799 if(-f $Candidate) {
6800 $HPath = $Candidate;
6801 }
6802 }
6803 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006804 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006805 }
6806 next if(not $HPath);
6807 if($HPath eq $AbsPath) {
6808 next;
6809 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006810
6811 if($Debug)
6812 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006813# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6814# {
6815# print STDERR "$AbsPath -> $HPath\n";
6816# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006817 }
6818
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006819 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6820 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006821 { # only include <...>, skip include "..." prefixes
6822 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6823 }
6824 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6825 {
6826 if($IncPath eq $AbsPath) {
6827 next;
6828 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006829 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6830 if($RIncType==-1)
6831 { # include "..."
6832 $RIncType = $IncType;
6833 }
6834 elsif($RIncType==2)
6835 {
6836 if($IncType!=-1) {
6837 $RIncType = $IncType;
6838 }
6839 }
6840 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006841 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6842 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6843 }
6844 }
6845 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6846 {
6847 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6848 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6849 { # distinguish math.h from glibc and math.h from the tested library
6850 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6851 last;
6852 }
6853 }
6854 }
6855 pop(@RecurInclude);
6856 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6857}
6858
6859sub find_in_framework($$$)
6860{
6861 my ($Header, $Framework, $LibVersion) = @_;
6862 return "" if(not $Header or not $Framework or not $LibVersion);
6863 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6864 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6865 }
6866 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6867 {
6868 if(get_filename($Dependency) eq $Framework
6869 and -f get_dirname($Dependency)."/".$Header) {
6870 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6871 }
6872 }
6873 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6874}
6875
6876sub find_in_defaults($)
6877{
6878 my $Header = $_[0];
6879 return "" if(not $Header);
6880 if(defined $Cache{"find_in_defaults"}{$Header}) {
6881 return $Cache{"find_in_defaults"}{$Header};
6882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006883 foreach my $Dir (@DefaultIncPaths,
6884 @DefaultGccPaths,
6885 @DefaultCppPaths,
6886 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006887 {
6888 next if(not $Dir);
6889 if(-f $Dir."/".$Header) {
6890 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6891 }
6892 }
6893 return ($Cache{"find_in_defaults"}{$Header}="");
6894}
6895
6896sub cmp_paths($$)
6897{
6898 my ($Path1, $Path2) = @_;
6899 my @Parts1 = split(/[\/\\]/, $Path1);
6900 my @Parts2 = split(/[\/\\]/, $Path2);
6901 foreach my $Num (0 .. $#Parts1)
6902 {
6903 my $Part1 = $Parts1[$Num];
6904 my $Part2 = $Parts2[$Num];
6905 if($GlibcDir{$Part1}
6906 and not $GlibcDir{$Part2}) {
6907 return 1;
6908 }
6909 elsif($GlibcDir{$Part2}
6910 and not $GlibcDir{$Part1}) {
6911 return -1;
6912 }
6913 elsif($Part1=~/glib/
6914 and $Part2!~/glib/) {
6915 return 1;
6916 }
6917 elsif($Part1!~/glib/
6918 and $Part2=~/glib/) {
6919 return -1;
6920 }
6921 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6922 return $CmpRes;
6923 }
6924 }
6925 return 0;
6926}
6927
6928sub checkRelevance($)
6929{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006930 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006933 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006934 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006935 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006936
6937 my $Name = lc(get_filename($Path));
6938 my $Dir = lc(get_dirname($Path));
6939
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006940 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006941
6942 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006943 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006944 my $Len = length($Token);
6945 next if($Len<=1);
6946 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6947 { # include/evolution-data-server-1.4/libebook/e-book.h
6948 return 1;
6949 }
6950 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006951 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006952 return 1;
6953 }
6954 }
6955 return 0;
6956}
6957
6958sub checkFamily(@)
6959{
6960 my @Paths = @_;
6961 return 1 if($#Paths<=0);
6962 my %Prefix = ();
6963 foreach my $Path (@Paths)
6964 {
6965 if($SystemRoot) {
6966 $Path = cut_path_prefix($Path, $SystemRoot);
6967 }
6968 if(my $Dir = get_dirname($Path))
6969 {
6970 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6971 $Prefix{$Dir} += 1;
6972 $Prefix{get_dirname($Dir)} += 1;
6973 }
6974 }
6975 foreach (sort keys(%Prefix))
6976 {
6977 if(get_depth($_)>=3
6978 and $Prefix{$_}==$#Paths+1) {
6979 return 1;
6980 }
6981 }
6982 return 0;
6983}
6984
6985sub isAcceptable($$$)
6986{
6987 my ($Header, $Candidate, $LibVersion) = @_;
6988 my $HName = get_filename($Header);
6989 if(get_dirname($Header))
6990 { # with prefix
6991 return 1;
6992 }
6993 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6994 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6995 return 1;
6996 }
6997 if(checkRelevance($Candidate))
6998 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6999 return 1;
7000 }
7001 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7002 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7003 # /usr/include/qt4/Qt/qsslconfiguration.h
7004 return 1;
7005 }
7006 if($OStarget eq "symbian")
7007 {
7008 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7009 return 1;
7010 }
7011 }
7012 return 0;
7013}
7014
7015sub isRelevant($$$)
7016{ # disallow to search for "abstract" headers in too deep directories
7017 my ($Header, $Candidate, $LibVersion) = @_;
7018 my $HName = get_filename($Header);
7019 if($OStarget eq "symbian")
7020 {
7021 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7022 return 0;
7023 }
7024 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007025 if($OStarget ne "bsd")
7026 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007027 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7028 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7029 return 0;
7030 }
7031 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007032 if($OStarget ne "windows")
7033 {
7034 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7035 { # skip /usr/include/wine/msvcrt
7036 return 0;
7037 }
7038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007039 if(not get_dirname($Header)
7040 and $Candidate=~/[\/\\]wx[\/\\]/)
7041 { # do NOT search in system /wx/ directory
7042 # for headers without a prefix: sstream.h
7043 return 0;
7044 }
7045 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7046 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7047 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7048 return 0;
7049 }
7050 if($Candidate=~/[\/\\]asm-/
7051 and (my $Arch = getArch($LibVersion)) ne "unknown")
7052 { # arch-specific header files
7053 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7054 {# skip ../asm-arm/ if using x86 architecture
7055 return 0;
7056 }
7057 }
7058 my @Candidates = getSystemHeaders($HName, $LibVersion);
7059 if($#Candidates==1)
7060 { # unique header
7061 return 1;
7062 }
7063 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7064 if($#SCandidates==1)
7065 { # unique name
7066 return 1;
7067 }
7068 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7069 if(get_depth($Candidate)-$SystemDepth>=5)
7070 { # abstract headers in too deep directories
7071 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7072 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7073 return 0;
7074 }
7075 }
7076 if($Header eq "parser.h"
7077 and $Candidate!~/\/libxml2\//)
7078 { # select parser.h from xml2 library
7079 return 0;
7080 }
7081 if(not get_dirname($Header)
7082 and keys(%{$SystemHeaders{$HName}})>=3)
7083 { # many headers with the same name
7084 # like thread.h included without a prefix
7085 if(not checkFamily(@Candidates)) {
7086 return 0;
7087 }
7088 }
7089 return 1;
7090}
7091
7092sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007093{ # cache function
7094 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7095 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7096 }
7097 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7098}
7099
7100sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007101{
7102 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007103 if(-f $Header) {
7104 return $Header;
7105 }
7106 if(is_abs($Header) and not -f $Header)
7107 { # incorrect absolute path
7108 return "";
7109 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007110 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007111 { # too abstract configuration headers
7112 return "";
7113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007114 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 if($OSgroup ne "windows")
7116 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007117 if(defined $WinHeaders{lc($HName)}
7118 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007119 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007120 return "";
7121 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007122 }
7123 if($OSgroup ne "macos")
7124 {
7125 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007126 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 return "";
7128 }
7129 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007130
7131 if(defined $ObsoleteHeaders{$HName})
7132 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007133 return "";
7134 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007135 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7136 {
7137 if(defined $AlienHeaders{$HName}
7138 or defined $AlienHeaders{$Header})
7139 { # alien headers from other systems
7140 return "";
7141 }
7142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007143
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007144 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007145 { # search in default paths
7146 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007147 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 }
7149 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007150 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007152 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007153 }
7154 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7155 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7156 {
7157 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007158 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 }
7160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 # error
7162 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163}
7164
7165sub getSystemHeaders($$)
7166{
7167 my ($Header, $LibVersion) = @_;
7168 my @Candidates = ();
7169 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7170 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 next;
7173 }
7174 push(@Candidates, $Candidate);
7175 }
7176 return @Candidates;
7177}
7178
7179sub cut_path_prefix($$)
7180{
7181 my ($Path, $Prefix) = @_;
7182 return $Path if(not $Prefix);
7183 $Prefix=~s/[\/\\]+\Z//;
7184 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7185 return $Path;
7186}
7187
7188sub is_default_include_dir($)
7189{
7190 my $Dir = $_[0];
7191 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007192 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193}
7194
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007195sub identifyHeader($$)
7196{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007198 if(not $Header) {
7199 return "";
7200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007202 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7203 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007205 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206}
7207
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007208sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007209{ # search for header by absolute path, relative path or name
7210 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 if(-f $Header)
7212 { # it's relative or absolute path
7213 return get_abs_path($Header);
7214 }
7215 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7216 and my $HeaderDir = find_in_defaults($Header))
7217 { # search for libc headers in the /usr/include
7218 # for non-libc target library before searching
7219 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007220 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221 }
7222 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7223 { # search in the target library paths
7224 return $Path;
7225 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007226 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 { # search in the internal GCC include paths
7228 return $DefaultGccHeader{$Header};
7229 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007230 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007232 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007234 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235 { # search in the default G++ include paths
7236 return $DefaultCppHeader{$Header};
7237 }
7238 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7239 { # search everywhere in the system
7240 return $AnyPath;
7241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007242 elsif($OSgroup eq "macos")
7243 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7244 if(my $Dir = get_dirname($Header))
7245 {
7246 my $RelPath = "Headers\/".get_filename($Header);
7247 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007248 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007249 }
7250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007252 # cannot find anything
7253 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254}
7255
7256sub getLocation($)
7257{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007258 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7259 {
7260 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007261 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007264 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267sub getNameByInfo($)
7268{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007269 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007270 {
7271 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7272 {
7273 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7274 {
7275 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7276 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007277 my $Str = $1;
7278 if($CppMode{$Version}
7279 and $Str=~/\Ac99_(.+)\Z/)
7280 {
7281 if($CppKeywords_A{$1}) {
7282 $Str=$1;
7283 }
7284 }
7285 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007286 }
7287 }
7288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007289 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007290 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291}
7292
7293sub getTreeStr($)
7294{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007295 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7298 {
7299 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007300 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007301 and $Str=~/\Ac99_(.+)\Z/)
7302 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 if($CppKeywords_A{$1}) {
7304 $Str=$1;
7305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007307 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007310 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311}
7312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313sub getFuncShortName($)
7314{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007315 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007317 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007319 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007320 {
7321 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7322 {
7323 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7324 return "operator ".$RName;
7325 }
7326 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007327 }
7328 else
7329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007330 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7331 {
7332 if(my $Ind = $Operator_Indication{$1}) {
7333 return "operator".$Ind;
7334 }
7335 elsif(not $UnknownOperator{$1})
7336 {
7337 printMsg("WARNING", "unknown operator $1");
7338 $UnknownOperator{$1} = 1;
7339 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007340 }
7341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007342 }
7343 else
7344 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007345 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7346 return getTreeStr($1);
7347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007348 }
7349 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007350 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351}
7352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007353sub getFuncReturn($)
7354{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007355 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7356 {
7357 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7358 {
7359 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7360 return $1;
7361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
7363 }
7364 return "";
7365}
7366
7367sub getFuncOrig($)
7368{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007369 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7370 {
7371 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7372 return $1;
7373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007375 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007376}
7377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378sub unmangleArray(@)
7379{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007380 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381 { # MSVC mangling
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007382 if(defined $DisabledMSVCUnmangling) {
7383 return @_;
7384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385 my $UndNameCmd = get_CmdPath("undname");
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007386 if(not $UndNameCmd)
7387 {
7388 if($OSgroup eq "windows") {
7389 exitStatus("Not_Found", "can't find \"undname\"");
7390 }
7391 elsif(not defined $DisabledMSVCUnmangling)
7392 {
7393 printMsg("WARNING", "can't find \"undname\", disable MSVC unmangling");
7394 $DisabledMSVCUnmangling = 1;
7395 return @_;
7396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 }
7398 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007399 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 }
7401 else
7402 { # GCC mangling
7403 my $CppFiltCmd = get_CmdPath("c++filt");
7404 if(not $CppFiltCmd) {
7405 exitStatus("Not_Found", "can't find c++filt in PATH");
7406 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007407 if(not defined $CPPFILT_SUPPORT_FILE)
7408 {
7409 my $Info = `$CppFiltCmd -h 2>&1`;
7410 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7411 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007412 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007413 if($CPPFILT_SUPPORT_FILE)
7414 { # new versions of c++filt can take a file
7415 if($#_>$MAX_CPPFILT_FILE_SIZE)
7416 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7417 # this is fixed in the oncoming version of Binutils
7418 my @Half = splice(@_, 0, ($#_+1)/2);
7419 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007421 else
7422 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007423 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7424 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7425 if($?==139)
7426 { # segmentation fault
7427 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7428 }
7429 return split(/\n/, $Res);
7430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007431 }
7432 else
7433 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007434 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7435 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436 my @Half = splice(@_, 0, ($#_+1)/2);
7437 return (unmangleArray(@Half), unmangleArray(@_))
7438 }
7439 else
7440 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007442 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7443 if($?==139)
7444 { # segmentation fault
7445 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7446 }
7447 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448 }
7449 }
7450 }
7451}
7452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453sub get_ChargeLevel($$)
7454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007455 my ($Symbol, $LibVersion) = @_;
7456 return "" if($Symbol!~/\A(_Z|\?)/);
7457 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7458 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007460 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007462 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 return "[in-charge]";
7464 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007465 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 return "[not-in-charge]";
7467 }
7468 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007471 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 return "[in-charge]";
7473 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007474 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 return "[not-in-charge]";
7476 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007477 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 return "[in-charge-deleting]";
7479 }
7480 }
7481 }
7482 else
7483 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007484 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 return "[in-charge]";
7486 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007487 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 return "[not-in-charge]";
7489 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007490 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 return "[in-charge]";
7492 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007493 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 return "[not-in-charge]";
7495 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007496 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007497 return "[in-charge-deleting]";
7498 }
7499 }
7500 return "";
7501}
7502
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007503sub get_Signature_M($$)
7504{
7505 my ($Symbol, $LibVersion) = @_;
7506 my $Signature_M = $tr_name{$Symbol};
7507 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7508 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007509 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007510 }
7511 return $Signature_M;
7512}
7513
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514sub get_Signature($$)
7515{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 my ($Symbol, $LibVersion) = @_;
7517 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7518 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007520 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007521 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007522
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007523 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007524
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007525 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007526 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007527 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7528 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007529 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7530 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007531
7532 if(index($Symbol, "_ZTV")==0) {
7533 return "vtable for $ClassName [data]";
7534 }
7535
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007536 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007537 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7538 $Signature .= "~";
7539 }
7540 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007542 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007543 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 }
7545 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007546 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007548 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7549 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007551 else
7552 {
7553 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007554 }
7555 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007558 if($Pos eq "") {
7559 next;
7560 }
7561
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007562 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007563 if(not $ParamTypeId) {
7564 next;
7565 }
7566
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007567 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 if(not $ParamTypeName) {
7569 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7570 }
7571 foreach my $Typedef (keys(%ChangedTypedef))
7572 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007573 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7574 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007576 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007577 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7578 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007579 if($ParamName eq "this"
7580 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007581 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007582 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007583 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007584 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 }
7586 else {
7587 push(@ParamArray, $ParamTypeName);
7588 }
7589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007590 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7591 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007592 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 }
7594 else
7595 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007598 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007600 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7602 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007603 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7606 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007607 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007609 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7610 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007611 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007612 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 }
7614 }
7615 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007617 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618 }
7619 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007620 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007621 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007622 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007623}
7624
7625sub create_member_decl($$)
7626{
7627 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007628 if($TName=~/\([\*]+\)/)
7629 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007630 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7631 return $TName;
7632 }
7633 else
7634 {
7635 my @ArraySizes = ();
7636 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7637 push(@ArraySizes, $1);
7638 }
7639 return $TName." ".$Member.join("", @ArraySizes);
7640 }
7641}
7642
7643sub getFuncType($)
7644{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007645 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7646 {
7647 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7648 {
7649 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7650 {
7651 if($Type eq "method_type") {
7652 return "Method";
7653 }
7654 elsif($Type eq "function_type") {
7655 return "Function";
7656 }
7657 else {
7658 return "Other";
7659 }
7660 }
7661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007663 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007664}
7665
7666sub getFuncTypeId($)
7667{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007668 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7669 {
7670 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7671 return $1;
7672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007674 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007675}
7676
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007678{ # "._N" or "$_N" in older GCC versions
7679 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007680}
7681
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007682sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007683{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007684 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7685 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007686 }
7687
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007688 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007689
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007690 if($_[1] ne "S")
7691 {
7692 $N=~s/\A[ ]+//g;
7693 $N=~s/[ ]+\Z//g;
7694 $N=~s/[ ]{2,}/ /g;
7695 }
7696
7697 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007698
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007699 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7700
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007701 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007702
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007703 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7704 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007705
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007706 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007707
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007708 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007709
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007710 if($_[1] eq "S")
7711 {
7712 if(index($N, "operator")!=-1) {
7713 $N=~s/\b(operator[ ]*)> >/$1>>/;
7714 }
7715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007717 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007718
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007719 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720}
7721
7722sub get_HeaderDeps($$)
7723{
7724 my ($AbsPath, $LibVersion) = @_;
7725 return () if(not $AbsPath or not $LibVersion);
7726 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7727 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7728 }
7729 my %IncDir = ();
7730 detect_recursive_includes($AbsPath, $LibVersion);
7731 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7732 {
7733 next if(not $HeaderPath);
7734 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7735 my $Dir = get_dirname($HeaderPath);
7736 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7737 {
7738 my $Dep = $Dir;
7739 if($Prefix)
7740 {
7741 if($OSgroup eq "windows")
7742 { # case insensitive seach on windows
7743 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7744 next;
7745 }
7746 }
7747 elsif($OSgroup eq "macos")
7748 { # seach in frameworks
7749 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7750 {
7751 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7752 {# frameworks
7753 my ($HFramework, $HName) = ($1, $2);
7754 $Dep = $HFramework;
7755 }
7756 else
7757 {# mismatch
7758 next;
7759 }
7760 }
7761 }
7762 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7763 { # Linux, FreeBSD
7764 next;
7765 }
7766 }
7767 if(not $Dep)
7768 { # nothing to include
7769 next;
7770 }
7771 if(is_default_include_dir($Dep))
7772 { # included by the compiler
7773 next;
7774 }
7775 if(get_depth($Dep)==1)
7776 { # too short
7777 next;
7778 }
7779 if(isLibcDir($Dep))
7780 { # do NOT include /usr/include/{sys,bits}
7781 next;
7782 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007783 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 }
7785 }
7786 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7787 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7788}
7789
7790sub sortIncPaths($$)
7791{
7792 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007793 if(not $ArrRef or $#{$ArrRef}<0) {
7794 return $ArrRef;
7795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007796 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7797 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007798 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007799 return $ArrRef;
7800}
7801
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007802sub sortDeps($$$)
7803{
7804 if($Header_Dependency{$_[2]}{$_[0]}
7805 and not $Header_Dependency{$_[2]}{$_[1]}) {
7806 return 1;
7807 }
7808 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7809 and $Header_Dependency{$_[2]}{$_[1]}) {
7810 return -1;
7811 }
7812 return 0;
7813}
7814
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007815sub join_P($$)
7816{
7817 my $S = "/";
7818 if($OSgroup eq "windows") {
7819 $S = "\\";
7820 }
7821 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007822}
7823
7824sub get_namespace_additions($)
7825{
7826 my $NameSpaces = $_[0];
7827 my ($Additions, $AddNameSpaceId) = ("", 1);
7828 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7829 {
7830 next if($SkipNameSpaces{$Version}{$NS});
7831 next if(not $NS or $NameSpaces->{$NS}==-1);
7832 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7833 next if($NS=~/\A__/i);
7834 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007835 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7837 my @NS_Parts = split(/::/, $NS);
7838 next if($#NS_Parts==-1);
7839 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7840 foreach my $NS_Part (@NS_Parts)
7841 {
7842 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7843 $TypeDecl_Suffix .= "}";
7844 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007845 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007846 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7847 $Additions.=" $TypeDecl\n $FuncDecl\n";
7848 $AddNameSpaceId+=1;
7849 }
7850 return $Additions;
7851}
7852
7853sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007854{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007855 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007856 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007857 if($Fmt eq "windows")
7858 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007859 $Path=~s/\//\\/g;
7860 $Path=lc($Path);
7861 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007862 else
7863 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007864 $Path=~s/\\/\//g;
7865 }
7866 return $Path;
7867}
7868
7869sub inc_opt($$)
7870{
7871 my ($Path, $Style) = @_;
7872 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007873 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007874 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007875 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007876 return "-I\"".path_format($Path, "unix")."\"";
7877 }
7878 elsif($OSgroup eq "macos"
7879 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007880 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007881 return "-F".esc(get_dirname($Path));
7882 }
7883 else {
7884 return "-I".esc($Path);
7885 }
7886 }
7887 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007888 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007889 }
7890 return "";
7891}
7892
7893sub platformSpecs($)
7894{
7895 my $LibVersion = $_[0];
7896 my $Arch = getArch($LibVersion);
7897 if($OStarget eq "symbian")
7898 { # options for GCCE compiler
7899 my %Symbian_Opts = map {$_=>1} (
7900 "-D__GCCE__",
7901 "-DUNICODE",
7902 "-fexceptions",
7903 "-D__SYMBIAN32__",
7904 "-D__MARM_INTERWORK__",
7905 "-D_UNICODE",
7906 "-D__S60_50__",
7907 "-D__S60_3X__",
7908 "-D__SERIES60_3X__",
7909 "-D__EPOC32__",
7910 "-D__MARM__",
7911 "-D__EABI__",
7912 "-D__MARM_ARMV5__",
7913 "-D__SUPPORT_CPP_EXCEPTIONS__",
7914 "-march=armv5t",
7915 "-mapcs",
7916 "-mthumb-interwork",
7917 "-DEKA2",
7918 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7919 );
7920 return join(" ", keys(%Symbian_Opts));
7921 }
7922 elsif($OSgroup eq "windows"
7923 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7924 { # add options to MinGW compiler
7925 # to simulate the MSVC compiler
7926 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007927 "-D__unaligned=\" \"",
7928 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929 "-D_WIN32",
7930 "-D_STDCALL_SUPPORTED",
7931 "-D__int64=\"long long\"",
7932 "-D__int32=int",
7933 "-D__int16=short",
7934 "-D__int8=char",
7935 "-D__possibly_notnullterminated=\" \"",
7936 "-D__nullterminated=\" \"",
7937 "-D__nullnullterminated=\" \"",
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007938 "-D__assume=\" \"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939 "-D__w64=\" \"",
7940 "-D__ptr32=\" \"",
7941 "-D__ptr64=\" \"",
7942 "-D__forceinline=inline",
7943 "-D__inline=inline",
7944 "-D__uuidof(x)=IID()",
7945 "-D__try=",
7946 "-D__except(x)=",
7947 "-D__declspec(x)=__attribute__((x))",
7948 "-D__pragma(x)=",
7949 "-D_inline=inline",
7950 "-D__forceinline=__inline",
7951 "-D__stdcall=__attribute__((__stdcall__))",
7952 "-D__cdecl=__attribute__((__cdecl__))",
7953 "-D__fastcall=__attribute__((__fastcall__))",
7954 "-D__thiscall=__attribute__((__thiscall__))",
7955 "-D_stdcall=__attribute__((__stdcall__))",
7956 "-D_cdecl=__attribute__((__cdecl__))",
7957 "-D_fastcall=__attribute__((__fastcall__))",
7958 "-D_thiscall=__attribute__((__thiscall__))",
7959 "-DSHSTDAPI_(x)=x",
7960 "-D_MSC_EXTENSIONS",
7961 "-DSECURITY_WIN32",
7962 "-D_MSC_VER=1500",
7963 "-D_USE_DECLSPECS_FOR_SAL",
7964 "-D__noop=\" \"",
7965 "-DDECLSPEC_DEPRECATED=\" \"",
7966 "-D__builtin_alignof(x)=__alignof__(x)",
7967 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007968 if($Arch eq "x86")
7969 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007970 $MinGW_Opts{"-D_X86_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 $MinGW_Opts{"-D_M_IX86=300"}=1;
7972 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007973 elsif($Arch eq "x86_64")
7974 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007975 $MinGW_Opts{"-D_AMD64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007976 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007977 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007979 elsif($Arch eq "ia64")
7980 {
7981 $MinGW_Opts{"-D_IA64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007982 $MinGW_Opts{"-D_M_IA64=300"}=1;
7983 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007984 return join(" ", sort keys(%MinGW_Opts));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007985 }
7986 return "";
7987}
7988
7989my %C_Structure = map {$_=>1} (
7990# FIXME: Can't separate union and struct data types before dumping,
7991# so it sometimes cause compilation errors for unknown reason
7992# when trying to declare TYPE* tmp_add_class_N
7993# This is a list of such structures + list of other C structures
7994 "sigval",
7995 "sigevent",
7996 "sigaction",
7997 "sigvec",
7998 "sigstack",
7999 "timeval",
8000 "timezone",
8001 "rusage",
8002 "rlimit",
8003 "wait",
8004 "flock",
8005 "stat",
8006 "_stat",
8007 "stat32",
8008 "_stat32",
8009 "stat64",
8010 "_stat64",
8011 "_stati64",
8012 "if_nameindex",
8013 "usb_device",
8014 "sigaltstack",
8015 "sysinfo",
8016 "timeLocale",
8017 "tcp_debug",
8018 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008019 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008020 "timespec",
8021 "random_data",
8022 "drand48_data",
8023 "_IO_marker",
8024 "_IO_FILE",
8025 "lconv",
8026 "sched_param",
8027 "tm",
8028 "itimerspec",
8029 "_pthread_cleanup_buffer",
8030 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008031 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008032 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008033 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008034 "sigcontext",
8035 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008036 # Mac
8037 "_timex",
8038 "_class_t",
8039 "_category_t",
8040 "_class_ro_t",
8041 "_protocol_t",
8042 "_message_ref_t",
8043 "_super_message_ref_t",
8044 "_ivar_t",
8045 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008046);
8047
8048sub getCompileCmd($$$)
8049{
8050 my ($Path, $Opt, $Inc) = @_;
8051 my $GccCall = $GCC_PATH;
8052 if($Opt) {
8053 $GccCall .= " ".$Opt;
8054 }
8055 $GccCall .= " -x ";
8056 if($OSgroup eq "macos") {
8057 $GccCall .= "objective-";
8058 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008059
8060 if($EMERGENCY_MODE_48)
8061 { # workaround for GCC 4.8 (C only)
8062 $GccCall .= "c++";
8063 }
8064 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008065 { # compile as "C++" header
8066 # to obtain complete dump using GCC 4.0
8067 $GccCall .= "c++-header";
8068 }
8069 else
8070 { # compile as "C++" source
8071 # GCC 3.3 cannot compile headers
8072 $GccCall .= "c++";
8073 }
8074 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008075 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008076 $GccCall .= " ".$Opts;
8077 }
8078 # allow extra qualifications
8079 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008080 $GccCall .= " -fpermissive";
8081 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008082 if($NoStdInc)
8083 {
8084 $GccCall .= " -nostdinc";
8085 $GccCall .= " -nostdinc++";
8086 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008087 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008088 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008089 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008090 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008091 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008092 if($Inc)
8093 { # include paths
8094 $GccCall .= " ".$Inc;
8095 }
8096 return $GccCall;
8097}
8098
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008099sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008100{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008101 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008102 my %HeaderElems = (
8103 # Types
8104 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008105 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008106 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8107 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008108 "time.h" => ["time_t"],
8109 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008110 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8111 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008112 "stdbool.h" => ["_Bool"],
8113 "rpc/xdr.h" => ["bool_t"],
8114 "in_systm.h" => ["n_long", "n_short"],
8115 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008116 "arpa/inet.h" => ["fw_src", "ip_src"],
8117 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008118 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008119 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 );
8121 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008122 foreach (keys(%HeaderElems))
8123 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008124 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008125 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008126 }
8127 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008128 my %Types = ();
8129 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8130 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008131 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008132 }
8133 if(keys(%Types))
8134 {
8135 my %AddHeaders = ();
8136 foreach my $Type (keys(%Types))
8137 {
8138 if(my $Header = $AutoPreamble{$Type})
8139 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008140 if(my $Path = identifyHeader($Header, $LibVersion))
8141 {
8142 if(skipHeader($Path, $LibVersion)) {
8143 next;
8144 }
8145 $Path = path_format($Path, $OSgroup);
8146 $AddHeaders{$Path}{"Type"} = $Type;
8147 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008148 }
8149 }
8150 }
8151 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008152 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008153 }
8154 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008155 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008156}
8157
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008158sub checkCTags($)
8159{
8160 my $Path = $_[0];
8161 if(not $Path) {
8162 return;
8163 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008164 my $CTags = undef;
8165
8166 if($OSgroup eq "bsd")
8167 { # use ectags on BSD
8168 $CTags = get_CmdPath("ectags");
8169 if(not $CTags) {
8170 printMsg("WARNING", "can't find \'ectags\' program");
8171 }
8172 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008173 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008174 $CTags = get_CmdPath("ctags");
8175 }
8176 if(not $CTags)
8177 {
8178 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008179 return;
8180 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008181
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008182 if($OSgroup ne "linux")
8183 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008184 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkodd172162016-10-04 19:41:25 +03008185 if($Info!~/universal|exuberant/i)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008186 {
8187 printMsg("WARNING", "incompatible version of \'ctags\' program");
8188 return;
8189 }
8190 }
8191
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008192 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008193 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008194 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008195 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008196 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008197 open(CTAGS, "<", $Out);
8198 while(my $Line = <CTAGS>)
8199 {
8200 chomp($Line);
8201 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008202 if(defined $Intrinsic_Keywords{$Name})
8203 { # noise
8204 next;
8205 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008206 if($Type eq "n")
8207 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008208 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008209 next;
8210 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008211 if(index($Scpe, "struct:")==0) {
8212 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008214 if(index($Scpe, "namespace:")==0)
8215 {
8216 if($Scpe=~s/\Anamespace://) {
8217 $Name = $Scpe."::".$Name;
8218 }
8219 }
8220 $TUnit_NameSpaces{$Version}{$Name} = 1;
8221 }
8222 elsif($Type eq "p")
8223 {
8224 if(not $Scpe or index($Scpe, "namespace:")==0) {
8225 $TUnit_Funcs{$Version}{$Name} = 1;
8226 }
8227 }
8228 elsif($Type eq "x")
8229 {
8230 if(not $Scpe or index($Scpe, "namespace:")==0) {
8231 $TUnit_Vars{$Version}{$Name} = 1;
8232 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008233 }
8234 }
8235 close(CTAGS);
8236}
8237
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008238sub preChange($$)
8239{
8240 my ($HeaderPath, $IncStr) = @_;
8241
8242 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8243 my $Content = undef;
8244
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008245 if(not defined $MinGWCompat and $OStarget eq "windows"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008246 and get_dumpmachine($GCC_PATH)=~/mingw/i
8247 and $MinGWMode{$Version}!=-1)
8248 { # modify headers to compile by MinGW
8249 if(not $Content)
8250 { # preprocessing
8251 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8252 }
8253 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8254 { # __asm { ... }
8255 $MinGWMode{$Version}=1;
8256 }
8257 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8258 { # comments after preprocessing
8259 $MinGWMode{$Version}=1;
8260 }
8261 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8262 { # 0xffui8
8263 $MinGWMode{$Version}=1;
8264 }
8265
8266 if($MinGWMode{$Version}) {
8267 printMsg("INFO", "Using MinGW compatibility mode");
8268 }
8269 }
8270
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008271 if(defined $CxxIncompat and ($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8272 and $CppMode{$Version}!=-1 and not $CPP_HEADERS)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008273 { # rename C++ keywords in C code
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008274 printMsg("INFO", "Checking the code for C++ keywords");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008275 if(not $Content)
8276 { # preprocessing
8277 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8278 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008279
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008280 my $RegExp_C = join("|", keys(%CppKeywords_C));
8281 my $RegExp_F = join("|", keys(%CppKeywords_F));
8282 my $RegExp_O = join("|", keys(%CppKeywords_O));
8283
8284 my $Detected = undef;
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008285 my $Sentence_O = undef;
8286 my $Sentence_N = undef;
8287 my $Regex = undef;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008288
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008289 $Regex = qr/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/;
8290 while($Content=~/$Regex/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008291 { # MATCH:
8292 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008293 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008294 # unsigned private: 8;
8295 # DO NOT MATCH:
8296 # #pragma GCC visibility push(default)
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008297 $Sentence_O = "$1$2$3$4";
8298 $Sentence_N = "$1$2c99_$3$4";
8299
8300 if($Sentence_O=~/\s+decltype\(/)
8301 { # C++
8302 # decltype(nullptr)
8303 last;
8304 }
8305 else
8306 {
8307 $Content=~s/$Regex/$Sentence_N/g;
8308 $CppMode{$Version} = 1;
8309 if(not defined $Detected) {
8310 $Detected = $Sentence_O;
8311 }
8312 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008313 }
8314 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8315 { # MATCH:
8316 # int delete(...);
8317 # int explicit(...);
8318 # DO NOT MATCH:
8319 # void operator delete(...)
8320 $CppMode{$Version} = 1;
8321 $Detected = "$1$2$3" if(not defined $Detected);
8322 }
8323 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8324 { # MATCH:
8325 # int bool;
8326 # DO NOT MATCH:
8327 # bool X;
8328 # return *this;
8329 # throw;
8330 $CppMode{$Version} = 1;
8331 $Detected = "$1$2$3" if(not defined $Detected);
8332 }
8333 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8334 { # MATCH:
8335 # int operator(...);
8336 # DO NOT MATCH:
8337 # int operator()(...);
8338 $CppMode{$Version} = 1;
8339 $Detected = "$1$2$3" if(not defined $Detected);
8340 }
8341 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8342 { # MATCH:
8343 # int foo(int operator);
8344 # int foo(int operator, int other);
8345 # DO NOT MATCH:
8346 # int operator,(...);
8347 $CppMode{$Version} = 1;
8348 $Detected = "$1$2$3" if(not defined $Detected);
8349 }
8350 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8351 { # MATCH:
8352 # int foo(gboolean *bool);
8353 # DO NOT MATCH:
8354 # void setTabEnabled(int index, bool);
8355 $CppMode{$Version} = 1;
8356 $Detected = "$1$2$3" if(not defined $Detected);
8357 }
8358 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8359 { # MATCH:
8360 # int foo(int* this);
8361 # int bar(int this);
8362 # int baz(int throw);
8363 # DO NOT MATCH:
8364 # foo(X, this);
8365 $CppMode{$Version} = 1;
8366 $Detected = "$1$2$3$4" if(not defined $Detected);
8367 }
8368 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8369 { # MATCH:
8370 # struct template {...};
8371 # extern template foo(...);
8372 $CppMode{$Version} = 1;
8373 $Detected = "$1$2" if(not defined $Detected);
8374 }
8375
8376 if($CppMode{$Version} == 1)
8377 {
8378 if($Debug)
8379 {
8380 $Detected=~s/\A\s+//g;
8381 printMsg("INFO", "Detected code: \"$Detected\"");
8382 }
8383 }
8384
8385 # remove typedef enum NAME NAME;
8386 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8387 my $N = 0;
8388 while($N<=$#FwdTypedefs-1)
8389 {
8390 my $S = $FwdTypedefs[$N];
8391 if($S eq $FwdTypedefs[$N+1])
8392 {
8393 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008394 $CppMode{$Version} = 1;
8395
8396 if($Debug) {
8397 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8398 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008399 }
8400 $N+=2;
8401 }
8402
8403 if($CppMode{$Version}==1) {
8404 printMsg("INFO", "Using C++ compatibility mode");
8405 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008406 else {
8407 printMsg("INFO", "C++ keywords in the C code are not found");
8408 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008409 }
8410
8411 if($CppMode{$Version}==1
8412 or $MinGWMode{$Version}==1)
8413 {
8414 my $IPath = $TMP_DIR."/dump$Version.i";
8415 writeFile($IPath, $Content);
8416 return $IPath;
8417 }
8418
8419 return undef;
8420}
8421
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008422sub getDump()
8423{
8424 if(not $GCC_PATH) {
8425 exitStatus("Error", "internal error - GCC path is not set");
8426 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008427
8428 my @Headers = keys(%{$Registered_Headers{$Version}});
8429 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8430
8431 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8432
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008433 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008434 my $HeaderPath = $TmpHeaderPath;
8435
8436 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008437 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8439 {
8440 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008441 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008442 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008443 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008444 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8445 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008446 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008447 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008448 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008449 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8450 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008453 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008454
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008455 if($ExtraInfo)
8456 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008457 if($IncludeString) {
8458 writeFile($ExtraInfo."/include-string", $IncludeString);
8459 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008460 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8461 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008462
8463 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8464 {
8465 my $REDIR = "";
8466 foreach my $P1 (sort @Redirects) {
8467 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8468 }
8469 writeFile($ExtraInfo."/include-redirect", $REDIR);
8470 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008471 }
8472
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008473 if(not keys(%{$TargetHeaders{$Version}}))
8474 { # Target headers
8475 addTargetHeaders($Version);
8476 }
8477
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008478 # clean memory
8479 %RecursiveIncludes = ();
8480 %Header_Include_Prefix = ();
8481 %Header_Includes = ();
8482
8483 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008484 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008485 delete($Cache{"detect_header_includes"});
8486 delete($Cache{"selectSystemHeader"});
8487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008488 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008489 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8490 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008491
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008492 if($ExtraInfo)
8493 { # extra information for other tools
8494 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8495 }
8496
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008497 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008498 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008499 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008500
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008501 if($COMMON_LANGUAGE{$Version} eq "C++") {
8502 checkCTags($Pre);
8503 }
8504
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008505 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8506 { # try to correct the preprocessor output
8507 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 if($COMMON_LANGUAGE{$Version} eq "C++")
8511 { # add classes and namespaces to the dump
8512 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008513 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008514 or $MinGWMode{$Version}==1) {
8515 $CHdump .= " -fpreprocessed";
8516 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008517 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008519 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008520 chdir($ORIG_DIR);
8521 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8522 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 my $Content = readFile($ClassDump);
8524 foreach my $ClassInfo (split(/\n\n/, $Content))
8525 {
8526 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8527 {
8528 my $CName = $1;
8529 next if($CName=~/\A(__|_objc_|_opaque_)/);
8530 $TUnit_NameSpaces{$Version}{$CName} = -1;
8531 if($CName=~/\A[\w:]+\Z/)
8532 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008533 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008534 }
8535 if($CName=~/(\w[\w:]*)::/)
8536 { # namespaces
8537 my $NS = $1;
8538 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8539 $TUnit_NameSpaces{$Version}{$NS} = 1;
8540 }
8541 }
8542 }
8543 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8544 { # read v-tables (advanced approach)
8545 my ($CName, $VTable) = ($1, $2);
8546 $ClassVTable_Content{$Version}{$CName} = $VTable;
8547 }
8548 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008549 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8550 { # add user-defined namespaces
8551 $TUnit_NameSpaces{$Version}{$NS} = 1;
8552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008553 if($Debug)
8554 { # debug mode
8555 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008556 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008557 }
8558 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008559 }
8560
8561 # add namespaces and classes
8562 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8563 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008564 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008565 }
8566 # some GCC versions don't include class methods to the TU dump by default
8567 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008568 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008569 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8570 {
8571 next if($C_Structure{$CName});
8572 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008573 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008574 if(not $Force and $GCC_44
8575 and $OSgroup eq "linux")
8576 { # optimization for linux with GCC >= 4.4
8577 # disable this code by -force option
8578 if(index($CName, "::")!=-1)
8579 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008580 next;
8581 }
8582 }
8583 else
8584 {
8585 if($CName=~/\A(.+)::[^:]+\Z/
8586 and $TUnit_Classes{$Version}{$1})
8587 { # classes inside other classes
8588 next;
8589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008590 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008591 if(defined $TUnit_Funcs{$Version}{$CName})
8592 { # the same name for a function and type
8593 next;
8594 }
8595 if(defined $TUnit_Vars{$Version}{$CName})
8596 { # the same name for a variable and type
8597 next;
8598 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008599 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8600 }
8601 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008602 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 }
8604 }
8605 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8606 # create TU dump
8607 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008608 if($UserLang eq "C") {
8609 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8610 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008611 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008612 or $MinGWMode{$Version}==1) {
8613 $TUdump .= " -fpreprocessed";
8614 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008615 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008616 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8617 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008618 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008619 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008620 if($?)
8621 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008622 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008623 { # try to recompile
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008624 # FIXME: handle errors and try to recompile
8625 if($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008626 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008627 { # add auto preamble headers and try again
8628 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008629 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008630 foreach my $Num (0 .. $#Headers)
8631 {
8632 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008633 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8634 {
8635 push_U($Include_Preamble{$Version}, $Path);
8636 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008637 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008638 }
8639 resetLogging($Version);
8640 $TMP_DIR = tempdir(CLEANUP=>1);
8641 return getDump();
8642 }
8643 elsif($Cpp0xMode{$Version}!=-1
8644 and ($Errors=~/\Q-std=c++0x\E/
8645 or $Errors=~/is not a class or namespace/))
8646 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008647 if(check_gcc($GCC_PATH, "4.6"))
8648 {
8649 $Cpp0xMode{$Version}=-1;
8650 printMsg("INFO", "Enabling c++0x mode");
8651 resetLogging($Version);
8652 $TMP_DIR = tempdir(CLEANUP=>1);
8653 $CompilerOptions{$Version} .= " -std=c++0x";
8654 return getDump();
8655 }
8656 else {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008657 printMsg("WARNING", "Probably c++0x element detected");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008658 }
8659
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008660 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008661 #elsif($MinGWMode{$Version}==1)
8662 #{ # disable MinGW mode and try again
8663 # $MinGWMode{$Version}=-1;
8664 # resetLogging($Version);
8665 # $TMP_DIR = tempdir(CLEANUP=>1);
8666 # return getDump();
8667 #}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008668 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008669 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008670 else {
8671 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 printMsg("ERROR", "some errors occurred when compiling headers");
8674 printErrorLog($Version);
8675 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008676 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677 }
8678 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008679 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008680 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008681
8682 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8683 return $TUs[0];
8684 }
8685 else
8686 {
8687 my $Msg = "can't compile header(s)";
8688 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8689 $Msg .= "\nDid you install G++?";
8690 }
8691 exitStatus("Cannot_Compile", $Msg);
8692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693}
8694
8695sub cmd_file($)
8696{
8697 my $Path = $_[0];
8698 return "" if(not $Path or not -e $Path);
8699 if(my $CmdPath = get_CmdPath("file")) {
8700 return `$CmdPath -b \"$Path\"`;
8701 }
8702 return "";
8703}
8704
8705sub getIncString($$)
8706{
8707 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008708 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008709 my $String = "";
8710 foreach (@{$ArrRef}) {
8711 $String .= " ".inc_opt($_, $Style);
8712 }
8713 return $String;
8714}
8715
8716sub getIncPaths(@)
8717{
8718 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008719 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 if($INC_PATH_AUTODETECT{$Version})
8721 { # auto-detecting dependencies
8722 my %Includes = ();
8723 foreach my $HPath (@HeaderPaths)
8724 {
8725 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8726 {
8727 if($Skip_Include_Paths{$Version}{$Dir}) {
8728 next;
8729 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008730 if($SystemRoot)
8731 {
8732 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8733 next;
8734 }
8735 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008736 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008737 }
8738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008739 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008740 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008741 }
8742 }
8743 else
8744 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008745 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008746 }
8747 return \@IncPaths;
8748}
8749
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008750sub push_U($@)
8751{ # push unique
8752 if(my $Array = shift @_)
8753 {
8754 if(@_)
8755 {
8756 my %Exist = map {$_=>1} @{$Array};
8757 foreach my $Elem (@_)
8758 {
8759 if(not defined $Exist{$Elem})
8760 {
8761 push(@{$Array}, $Elem);
8762 $Exist{$Elem} = 1;
8763 }
8764 }
8765 }
8766 }
8767}
8768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769sub callPreprocessor($$$)
8770{
8771 my ($Path, $Inc, $LibVersion) = @_;
8772 return "" if(not $Path or not -f $Path);
8773 my $IncludeString=$Inc;
8774 if(not $Inc) {
8775 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8776 }
8777 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008778 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008779 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008780 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781}
8782
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008783sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784{ # native "find" is much faster than File::Find (~6x)
8785 # also the File::Find doesn't support --maxdepth N option
8786 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008787 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008788 return () if(not $Path or not -e $Path);
8789 if($OSgroup eq "windows")
8790 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008791 $Path = get_abs_path($Path);
8792 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008793 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794 if($MaxDepth!=1) {
8795 $Cmd .= " /S";
8796 }
8797 if($Type eq "d") {
8798 $Cmd .= " /AD";
8799 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008800 elsif($Type eq "f") {
8801 $Cmd .= " /A-D";
8802 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008803 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008804 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008805 {
8806 if(not $UseRegex)
8807 { # FIXME: how to search file names in MS shell?
8808 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008809 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008810 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008812 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 }
8814 my @AbsPaths = ();
8815 foreach my $File (@Files)
8816 {
8817 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008818 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008819 }
8820 if($Type eq "f" and not -f $File)
8821 { # skip dirs
8822 next;
8823 }
8824 push(@AbsPaths, path_format($File, $OSgroup));
8825 }
8826 if($Type eq "d") {
8827 push(@AbsPaths, $Path);
8828 }
8829 return @AbsPaths;
8830 }
8831 else
8832 {
8833 my $FindCmd = get_CmdPath("find");
8834 if(not $FindCmd) {
8835 exitStatus("Not_Found", "can't find a \"find\" command");
8836 }
8837 $Path = get_abs_path($Path);
8838 if(-d $Path and -l $Path
8839 and $Path!~/\/\Z/)
8840 { # for directories that are symlinks
8841 $Path.="/";
8842 }
8843 my $Cmd = $FindCmd." \"$Path\"";
8844 if($MaxDepth) {
8845 $Cmd .= " -maxdepth $MaxDepth";
8846 }
8847 if($Type) {
8848 $Cmd .= " -type $Type";
8849 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008850 if($Name and not $UseRegex)
8851 { # wildcards
8852 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008854 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008855 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008856 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8857 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008858 my @Files = split(/\n/, $Res);
8859 if($Name and $UseRegex)
8860 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008861 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008862 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008863 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864 }
8865}
8866
8867sub unpackDump($)
8868{
8869 my $Path = $_[0];
8870 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872 $Path = get_abs_path($Path);
8873 $Path = path_format($Path, $OSgroup);
8874 my ($Dir, $FileName) = separate_path($Path);
8875 my $UnpackDir = $TMP_DIR."/unpack";
8876 rmtree($UnpackDir);
8877 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 if($FileName=~s/\Q.zip\E\Z//g)
8880 { # *.zip
8881 my $UnzipCmd = get_CmdPath("unzip");
8882 if(not $UnzipCmd) {
8883 exitStatus("Not_Found", "can't find \"unzip\" command");
8884 }
8885 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008886 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008887 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008888 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008889 }
8890 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008891 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 if(not @Contents) {
8893 exitStatus("Error", "can't extract \'$Path\'");
8894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008895 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008897 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008898 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008899 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008900 if($OSgroup eq "windows")
8901 { # -xvzf option is not implemented in tar.exe (2003)
8902 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8903 my $TarCmd = get_CmdPath("tar");
8904 if(not $TarCmd) {
8905 exitStatus("Not_Found", "can't find \"tar\" command");
8906 }
8907 my $GzipCmd = get_CmdPath("gzip");
8908 if(not $GzipCmd) {
8909 exitStatus("Not_Found", "can't find \"gzip\" command");
8910 }
8911 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008912 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 if($?) {
8914 exitStatus("Error", "can't extract \'$Path\'");
8915 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008916 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008918 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008919 }
8920 chdir($ORIG_DIR);
8921 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008922 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008923 if(not @Contents) {
8924 exitStatus("Error", "can't extract \'$Path\'");
8925 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008926 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008927 }
8928 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008929 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 my $TarCmd = get_CmdPath("tar");
8931 if(not $TarCmd) {
8932 exitStatus("Not_Found", "can't find \"tar\" command");
8933 }
8934 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008935 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008936 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008937 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 }
8939 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008940 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008941 if(not @Contents) {
8942 exitStatus("Error", "can't extract \'$Path\'");
8943 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008944 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008945 }
8946 }
8947}
8948
8949sub createArchive($$)
8950{
8951 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008952 if(not $To) {
8953 $To = ".";
8954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008955 if(not $Path or not -e $Path
8956 or not -d $To) {
8957 return "";
8958 }
8959 my ($From, $Name) = separate_path($Path);
8960 if($OSgroup eq "windows")
8961 { # *.zip
8962 my $ZipCmd = get_CmdPath("zip");
8963 if(not $ZipCmd) {
8964 exitStatus("Not_Found", "can't find \"zip\"");
8965 }
8966 my $Pkg = $To."/".$Name.".zip";
8967 unlink($Pkg);
8968 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008969 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008970 if($?)
8971 { # cannot allocate memory (or other problems with "zip")
8972 unlink($Path);
8973 exitStatus("Error", "can't pack the ABI dump: ".$!);
8974 }
8975 chdir($ORIG_DIR);
8976 unlink($Path);
8977 return $Pkg;
8978 }
8979 else
8980 { # *.tar.gz
8981 my $TarCmd = get_CmdPath("tar");
8982 if(not $TarCmd) {
8983 exitStatus("Not_Found", "can't find \"tar\"");
8984 }
8985 my $GzipCmd = get_CmdPath("gzip");
8986 if(not $GzipCmd) {
8987 exitStatus("Not_Found", "can't find \"gzip\"");
8988 }
8989 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8990 unlink($Pkg);
8991 chdir($From);
8992 system($TarCmd, "-czf", $Pkg, $Name);
8993 if($?)
8994 { # cannot allocate memory (or other problems with "tar")
8995 unlink($Path);
8996 exitStatus("Error", "can't pack the ABI dump: ".$!);
8997 }
8998 chdir($ORIG_DIR);
8999 unlink($Path);
9000 return $To."/".$Name.".tar.gz";
9001 }
9002}
9003
9004sub is_header_file($)
9005{
9006 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9007 return $_[0];
9008 }
9009 return 0;
9010}
9011
9012sub is_not_header($)
9013{
9014 if($_[0]=~/\.\w+\Z/
9015 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9016 return 1;
9017 }
9018 return 0;
9019}
9020
9021sub is_header($$$)
9022{
9023 my ($Header, $UserDefined, $LibVersion) = @_;
9024 return 0 if(-d $Header);
9025 if(-f $Header) {
9026 $Header = get_abs_path($Header);
9027 }
9028 else
9029 {
9030 if(is_abs($Header))
9031 { # incorrect absolute path
9032 return 0;
9033 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009034 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009035 $Header = $HPath;
9036 }
9037 else
9038 { # can't find header
9039 return 0;
9040 }
9041 }
9042 if($Header=~/\.\w+\Z/)
9043 { # have an extension
9044 return is_header_file($Header);
9045 }
9046 else
9047 {
9048 if($UserDefined==2)
9049 { # specified on the command line
9050 if(cmd_file($Header)!~/HTML|XML/i) {
9051 return $Header;
9052 }
9053 }
9054 elsif($UserDefined)
9055 { # specified in the XML-descriptor
9056 # header file without an extension
9057 return $Header;
9058 }
9059 else
9060 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009061 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009062 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009063 { # !~/HTML|XML|shared|dynamic/i
9064 return $Header;
9065 }
9066 }
9067 }
9068 return 0;
9069}
9070
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009071sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072{
9073 my $LibVersion = $_[0];
9074 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9075 {
9076 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009077 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009078
9079 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9080 detect_recursive_includes($RegHeader, $LibVersion);
9081 }
9082
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009083 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9084 {
9085 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009086
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009087 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009088 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9089 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009090 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009091 }
9092 }
9093 }
9094}
9095
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009096sub familiarDirs($$)
9097{
9098 my ($D1, $D2) = @_;
9099 if($D1 eq $D2) {
9100 return 1;
9101 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009102
9103 my $U1 = index($D1, "/usr/");
9104 my $U2 = index($D2, "/usr/");
9105
9106 if($U1==0 and $U2!=0) {
9107 return 0;
9108 }
9109
9110 if($U2==0 and $U1!=0) {
9111 return 0;
9112 }
9113
9114 if(index($D2, $D1."/")==0) {
9115 return 1;
9116 }
9117
9118 # /usr/include/DIR
9119 # /home/user/DIR
9120
9121 my $DL = get_depth($D1);
9122
9123 my @Dirs1 = ($D1);
9124 while($DL - get_depth($D1)<=2
9125 and get_depth($D1)>=4
9126 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9127 push(@Dirs1, $D1);
9128 }
9129
9130 my @Dirs2 = ($D2);
9131 while(get_depth($D2)>=4
9132 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9133 push(@Dirs2, $D2);
9134 }
9135
9136 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009137 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009138 foreach my $P2 (@Dirs2)
9139 {
9140
9141 if($P1 eq $P2) {
9142 return 1;
9143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009144 }
9145 }
9146 return 0;
9147}
9148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009149sub readHeaders($)
9150{
9151 $Version = $_[0];
9152 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9153 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 if($Debug)
9155 { # debug mode
9156 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009157 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009158 }
9159 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160}
9161
9162sub prepareTypes($)
9163{
9164 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009165 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009166 { # support for old ABI dumps
9167 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009168 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9171 if($TName=~/\A(\w+)::(\w+)/) {
9172 my ($P1, $P2) = ($1, $2);
9173 if($P1 eq $P2) {
9174 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009176 else {
9177 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009180 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 }
9182 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009183 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009184 { # support for old ABI dumps
9185 # V < 2.5: array size == "number of elements"
9186 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009187 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009188 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009189 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009190 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009191 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009192 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009193 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009194 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009195 $Size *= $Base{"Size"};
9196 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009197 }
9198 else
9199 { # array[] is a pointer
9200 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009201 }
9202 }
9203 }
9204 }
9205 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009206 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009207 { # support for old ABI dumps
9208 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009209 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009210 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009211 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009212 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009214 my %Type = get_Type($TypeId, $LibVersion);
9215 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9216 my %Type2 = get_Type($TypeId_2, $V2);
9217 if($Type{"Size"} ne $Type2{"Size"}) {
9218 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009219 }
9220 }
9221 }
9222 }
9223}
9224
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009225sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009226{
9227 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228
9229 if(not keys(%{$SymbolInfo{$LibVersion}}))
9230 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009231 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009232 {
9233 if($CheckHeadersOnly) {
9234 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9235 }
9236 else {
9237 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9238 }
9239 }
9240 }
9241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009242 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009243 if(not checkDump(1, "2.10")
9244 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009245 { # different formats
9246 $Remangle = 1;
9247 }
9248 if($CheckHeadersOnly)
9249 { # different languages
9250 if($UserLang)
9251 { # --lang=LANG for both versions
9252 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9253 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9254 {
9255 if($UserLang eq "C++")
9256 { # remangle symbols
9257 $Remangle = 1;
9258 }
9259 elsif($UserLang eq "C")
9260 { # remove mangling
9261 $Remangle = -1;
9262 }
9263 }
9264 }
9265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009266
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009267 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009269 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009270 { # support for old ABI dumps
9271 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9272 {
9273 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9274 {
9275 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9276 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009277 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009278 if(defined $DVal and $DVal ne "")
9279 {
9280 if($TName eq "char") {
9281 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9282 }
9283 elsif($TName eq "bool") {
9284 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9285 }
9286 }
9287 }
9288 }
9289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009290 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009292 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9293 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009294 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009295 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9296 # + support for old ABI dumps
9297 next;
9298 }
9299 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009300 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009302 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009303 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009304
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009305 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009306 if(not checkDump(1, "2.12")
9307 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009308 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009309 if($ShortName eq "operator>>")
9310 {
9311 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9312 { # corrected mangling of operator>>
9313 $SRemangle = 1;
9314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009316 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9317 {
9318 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9319 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9320 { # corrected mangling of const global data
9321 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9322 # and incorrectly mangled by old ACC versions
9323 $SRemangle = 1;
9324 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009325 }
9326 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009327 if(not $CheckHeadersOnly)
9328 { # support for old ABI dumps
9329 if(not checkDump(1, "2.17")
9330 or not checkDump(2, "2.17"))
9331 {
9332 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9333 {
9334 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9335 {
9336 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9337 {
9338 $MnglName = $ShortName;
9339 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9340 }
9341 }
9342 }
9343 }
9344 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009345 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 { # support for old ABI dumps: some symbols are not mangled in old dumps
9347 # mangle both sets of symbols (old and new)
9348 # NOTE: remangling all symbols by the same mangler
9349 if($MnglName=~/\A_ZN(V|)K/)
9350 { # mangling may be incorrect on old ABI dumps
9351 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009352 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009353 }
9354 if($MnglName=~/\A_ZN(K|)V/)
9355 { # mangling may be incorrect on old ABI dumps
9356 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009357 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009358 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009359 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9360 or (not $ClassID and $CheckHeadersOnly)
9361 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9362 { # support for old ABI dumps, GCC >= 4.0
9363 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009364 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009366 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009367 $MangledNames{$LibVersion}{$MnglName} = 1;
9368 }
9369 }
9370 }
9371 elsif($Remangle==-1)
9372 { # remove mangling
9373 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009374 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 if(not $MnglName) {
9377 next;
9378 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009379
9380 # NOTE: duplicated entries in the ABI Dump
9381 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9382 {
9383 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9384 {
9385 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9386 {
9387 next;
9388 }
9389 }
9390 }
9391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9393 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009394 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009397 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009398 { # support for old dumps
9399 # add "Volatile" attribute
9400 if($MnglName=~/_Z(K|)V/) {
9401 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9402 }
9403 }
9404 # symbol and its symlink have same signatures
9405 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009406 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009409 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9410 {
9411 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009412
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009413 if($SymVer{$LibVersion}{$Alias}) {
9414 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9415 }
9416 }
9417
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009418 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009419 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 }
9421 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9422 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9423 }
9424 if($ExtendedCheck)
9425 { # --ext option
9426 addExtension($LibVersion);
9427 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009428
9429 # clean memory
9430 delete($SymbolInfo{$LibVersion});
9431
9432 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 { # detect allocable classes with public exported constructors
9434 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009435 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009436 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009438 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9440 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009442 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009444 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009445 $AllocableClass{$LibVersion}{$ClassName} = 1;
9446 }
9447 }
9448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009449 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009451 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009453 if($CheckHeadersOnly)
9454 {
9455 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9456 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9457 { # all symbols except non-virtual inline
9458 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9459 }
9460 }
9461 else {
9462 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 }
9464 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009466 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 }
9468 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009469 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009471 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009473 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009474 if(defined $Base{"Type"}
9475 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 if($Name=~/<([^<>\s]+)>/)
9479 {
9480 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9481 $ReturnedClass{$LibVersion}{$Tid} = 1;
9482 }
9483 }
9484 else {
9485 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9486 }
9487 }
9488 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009489 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009491 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009492 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009493 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009494 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009495 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009496 if($Base{"Type"}=~/Struct|Class/)
9497 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009498 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009499 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9500 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009503 }
9504 }
9505 }
9506 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009507
9508 # mapping {short name => symbols}
9509 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009510 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009511 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009512 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009513 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009514 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009515 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009516 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009517 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009520 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 }
9522 }
9523 }
9524 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009525
9526 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009527 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009529 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009530 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009531 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9532 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009533 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009534 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009535 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009536 $ClassNames{$LibVersion}{$TName} = 1;
9537 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009539 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9540 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009541 }
9542 }
9543 }
9544 }
9545 }
9546}
9547
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009549{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009550 my ($Tid, $LibVersion) = @_;
9551 if(not $Tid) {
9552 return $Tid;
9553 }
9554
9555 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9556 {
9557 if($TName_Tid{$LibVersion}{$Name}) {
9558 return $TName_Tid{$LibVersion}{$Name};
9559 }
9560 }
9561
9562 return $Tid;
9563}
9564
9565sub register_SymbolUsage($$$)
9566{
9567 my ($InfoId, $UsedType, $LibVersion) = @_;
9568
9569 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9570 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9571 {
9572 register_TypeUsage($RTid, $UsedType, $LibVersion);
9573 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9574 }
9575 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9576 {
9577 register_TypeUsage($FCid, $UsedType, $LibVersion);
9578 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9579
9580 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9581 { # register "this" pointer
9582 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9583 }
9584 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9585 { # register "this" pointer (const method)
9586 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9587 }
9588 }
9589 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9590 {
9591 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9592 {
9593 register_TypeUsage($PTid, $UsedType, $LibVersion);
9594 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9595 }
9596 }
9597 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9598 {
9599 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9600 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9601 register_TypeUsage($TTid, $UsedType, $LibVersion);
9602 }
9603 }
9604}
9605
9606sub register_TypeUsage($$$)
9607{
9608 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009609 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009610 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009611 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009612 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009613 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009614 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009615 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009616
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009617 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009618 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009620 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009622 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9623 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9624 }
9625 }
9626
9627 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9628 {
9629 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009630 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009631 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009632 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9633 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9636 {
9637 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9638 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640 }
9641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009642 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009643 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009644 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009645 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9646 {
9647 register_TypeUsage($MTid, $UsedType, $LibVersion);
9648 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009649 }
9650 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009651 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009652 or $TInfo{"Type"} eq "MethodPtr"
9653 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009654 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009656 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009657 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009658 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009659 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009660 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9661 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009662 }
9663 }
9664 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009665 if($TInfo{"Type"} eq "FieldPtr")
9666 {
9667 if(my $RTid = $TInfo{"Return"}) {
9668 register_TypeUsage($RTid, $UsedType, $LibVersion);
9669 }
9670 if(my $CTid = $TInfo{"Class"}) {
9671 register_TypeUsage($CTid, $UsedType, $LibVersion);
9672 }
9673 }
9674 if($TInfo{"Type"} eq "MethodPtr")
9675 {
9676 if(my $CTid = $TInfo{"Class"}) {
9677 register_TypeUsage($CTid, $UsedType, $LibVersion);
9678 }
9679 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009681 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009682 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009683 $UsedType->{$TypeId} = 1;
9684 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9685 {
9686 register_TypeUsage($BTid, $UsedType, $LibVersion);
9687 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9688 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009689 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009690 else
9691 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9692 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009693 }
9694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009695}
9696
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009697sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009698{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009699 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9700
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009701 if($Level eq "Dump")
9702 {
9703 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9704 { # TODO: check if this symbol is from
9705 # base classes of other target symbols
9706 return 1;
9707 }
9708 }
9709
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009710 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9711 { # stdc++ interfaces
9712 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009713 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714
9715 my $Target = 0;
9716 if(my $Header = $SInfo->{"Header"}) {
9717 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9718 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009719 if($ExtendedCheck)
9720 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009721 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009722 $Target = 1;
9723 }
9724 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009725 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009726 {
9727 if($Target)
9728 {
9729 if($Level eq "Dump")
9730 { # dumped
9731 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009732 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009733 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009734 return 1;
9735 }
9736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009737 else {
9738 return 1;
9739 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009740 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009741 elsif($Level eq "Source")
9742 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009743 return 1;
9744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009745 elsif($Level eq "Binary")
9746 { # checked
9747 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9748 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9749 return 1;
9750 }
9751 }
9752 }
9753 }
9754 else
9755 { # library is available
9756 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9757 { # exported symbols
9758 return 1;
9759 }
9760 if($Level eq "Dump")
9761 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009762 if($BinaryOnly)
9763 {
9764 if($SInfo->{"Data"})
9765 {
9766 if($Target) {
9767 return 1;
9768 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009769 }
9770 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009771 else
9772 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009773 if($Target) {
9774 return 1;
9775 }
9776 }
9777 }
9778 elsif($Level eq "Source")
9779 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009780 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009781 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009782 { # skip LOCAL symbols
9783 if($Target) {
9784 return 1;
9785 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009786 }
9787 }
9788 elsif($Level eq "Binary")
9789 { # checked
9790 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9791 {
9792 if($Target) {
9793 return 1;
9794 }
9795 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009796 }
9797 }
9798 return 0;
9799}
9800
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009801sub cleanDump($)
9802{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009803 my $LibVersion = $_[0];
9804 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9805 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009806 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9807 {
9808 delete($SymbolInfo{$LibVersion}{$InfoId});
9809 next;
9810 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009811 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009812 if(not $MnglName)
9813 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009814 delete($SymbolInfo{$LibVersion}{$InfoId});
9815 next;
9816 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009817 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009818 if(not $ShortName)
9819 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009820 delete($SymbolInfo{$LibVersion}{$InfoId});
9821 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009823 if($MnglName eq $ShortName)
9824 { # remove duplicate data
9825 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009826 }
9827 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9828 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9829 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009830 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9831 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9832 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009833 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009835 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009836 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009837 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9838 {
9839 delete($TypeInfo{$LibVersion}{$Tid});
9840 next;
9841 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009842 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009843 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009844 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009845 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9846 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9847 }
9848 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009849 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9850 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9851 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009852 }
9853}
9854
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009855sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009856{
9857 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009858
9859 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9860 {
9861 if(defined $TypeInfo{$LibVersion}{$Dupl})
9862 {
9863 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9864 { # duplicate
9865 return 0;
9866 }
9867 }
9868 }
9869
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009870 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9871
9872 if(isBuiltIn($THeader)) {
9873 return 0;
9874 }
9875
9876 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9877 return 0;
9878 }
9879
9880 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9881 return 0;
9882 }
9883
9884 if(selfTypedef($Tid, $LibVersion)) {
9885 return 0;
9886 }
9887
9888 if(not isTargetType($Tid, $LibVersion)) {
9889 return 0;
9890 }
9891
9892 return 0;
9893}
9894
9895sub isTargetType($$)
9896{
9897 my ($Tid, $LibVersion) = @_;
9898
9899 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9900 { # derived
9901 return 1;
9902 }
9903
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009904 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009905 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009906 if(not is_target_header($THeader, $LibVersion))
9907 { # from target headers
9908 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009909 }
9910 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009911 else
9912 { # NOTE: if type is defined in source
9913 if($UsedDump{$LibVersion}{"Public"})
9914 {
9915 if(isPrivateABI($Tid, $LibVersion)) {
9916 return 0;
9917 }
9918 else {
9919 return 1;
9920 }
9921 }
9922 else {
9923 return 0;
9924 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009925 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009926
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009927 if($SkipInternalTypes)
9928 {
9929 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9930 {
9931 return 0;
9932 }
9933 }
9934
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009935 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009936}
9937
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009938sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009939{ # remove unused data types from the ABI dump
9940 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009941
9942 my %UsedType = ();
9943
9944 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009945 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009946 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009947 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009948 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009949 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009950 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009951 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009952 next;
9953 }
9954
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009955 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009956 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009957 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009958 {
9959 my %Tree = ();
9960 register_TypeUsage($Tid, \%Tree, $LibVersion);
9961
9962 my $Tmpl = 0;
9963 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9964 {
9965 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9966 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9967 {
9968 $Tmpl = 1;
9969 last;
9970 }
9971 }
9972 if(not $Tmpl)
9973 {
9974 foreach (keys(%Tree)) {
9975 $UsedType{$_} = 1;
9976 }
9977 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009978 }
9979 }
9980 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009981
9982 my %Delete = ();
9983
9984 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009985 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009986 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009987 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009988 next;
9989 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009990
9991 if($Kind eq "Extra")
9992 {
9993 my %Tree = ();
9994 register_TypeUsage($Tid, \%Tree, $LibVersion);
9995
9996 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9997 {
9998 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9999 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10000 {
10001 $Delete{$Tid} = 1;
10002 last;
10003 }
10004 }
10005 }
10006 else
10007 {
10008 # remove type
10009 delete($TypeInfo{$LibVersion}{$Tid});
10010 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010011 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010012
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010013 if($Kind eq "Extra")
10014 { # remove duplicates
10015 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10016 {
10017 if($UsedType{$Tid})
10018 { # All & Extended
10019 next;
10020 }
10021
10022 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10023
10024 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10025 delete($TypeInfo{$LibVersion}{$Tid});
10026 }
10027 }
10028 }
10029
10030 foreach my $Tid (keys(%Delete))
10031 {
10032 delete($TypeInfo{$LibVersion}{$Tid});
10033 }
10034}
10035
10036sub check_Completeness($$)
10037{
10038 my ($Info, $LibVersion) = @_;
10039
10040 # data types
10041 if(defined $Info->{"Memb"})
10042 {
10043 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10044 {
10045 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10046 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10047 }
10048 }
10049 }
10050 if(defined $Info->{"Base"})
10051 {
10052 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10053 check_TypeInfo($Bid, $LibVersion);
10054 }
10055 }
10056 if(defined $Info->{"BaseType"}) {
10057 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10058 }
10059 if(defined $Info->{"TParam"})
10060 {
10061 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10062 {
10063 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10064 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10065 next;
10066 }
10067 if($TName eq "_BoolType") {
10068 next;
10069 }
10070 if($TName=~/\Asizeof\(/) {
10071 next;
10072 }
10073 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10074 check_TypeInfo($Tid, $LibVersion);
10075 }
10076 else
10077 {
10078 if(defined $Debug) {
10079 printMsg("WARNING", "missed type $TName");
10080 }
10081 }
10082 }
10083 }
10084
10085 # symbols
10086 if(defined $Info->{"Param"})
10087 {
10088 foreach my $Pos (keys(%{$Info->{"Param"}}))
10089 {
10090 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10091 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10092 }
10093 }
10094 }
10095 if(defined $Info->{"Return"}) {
10096 check_TypeInfo($Info->{"Return"}, $LibVersion);
10097 }
10098 if(defined $Info->{"Class"}) {
10099 check_TypeInfo($Info->{"Class"}, $LibVersion);
10100 }
10101}
10102
10103sub check_TypeInfo($$)
10104{
10105 my ($Tid, $LibVersion) = @_;
10106
10107 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10108 return;
10109 }
10110 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10111
10112 if(defined $TypeInfo{$LibVersion}{$Tid})
10113 {
10114 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10115 printMsg("ERROR", "missed type name ($Tid)");
10116 }
10117 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10118 }
10119 else {
10120 printMsg("ERROR", "missed type id $Tid");
10121 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010122}
10123
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010124sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010125{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010126 my ($TypeId, $LibVersion) = @_;
10127 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010128 if($Type{"Type"} eq "Typedef")
10129 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010130 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010131 if($Base{"Type"}=~/Class|Struct/)
10132 {
10133 if($Type{"Name"} eq $Base{"Name"}) {
10134 return 1;
10135 }
10136 elsif($Type{"Name"}=~/::(\w+)\Z/)
10137 {
10138 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10139 { # QPointer<QWidget>::QPointer
10140 return 1;
10141 }
10142 }
10143 }
10144 }
10145 return 0;
10146}
10147
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148sub addExtension($)
10149{
10150 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010151 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010152 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010153 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010154 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010155 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10156 $TName=~s/\A(struct|union|class|enum) //;
10157 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010158
10159 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10160 "Header" => "extended.h",
10161 "ShortName" => $Symbol,
10162 "MnglName" => $Symbol,
10163 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10164 );
10165
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010166 $ExtendedSymbols{$Symbol} = 1;
10167 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10168 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010169 }
10170 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010171 $ExtendedSymbols{"external_func_0"} = 1;
10172 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10173 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174}
10175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176sub findMethod($$$)
10177{
10178 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010179 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010180 {
10181 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10182 return $VirtMethodInClass;
10183 }
10184 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10185 return $VirtMethodInBaseClasses;
10186 }
10187 }
10188 return "";
10189}
10190
10191sub findMethod_Class($$$)
10192{
10193 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010194 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010195 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10196 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10197 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10198 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10199 { # search for interface with the same parameters suffix (overridden)
10200 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10201 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010202 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10203 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010204 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10205 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010206 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10207 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10208 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10209 return $Candidate;
10210 }
10211 }
10212 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010213 else
10214 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10216 return $Candidate;
10217 }
10218 }
10219 }
10220 }
10221 return "";
10222}
10223
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010224sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010226 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010227 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010228 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010229 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10230 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010231 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010232 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010234 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10235 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 { # pure virtual D2-destructors are marked as "virt" in the dump
10237 # virtual D2-destructors are NOT marked as "virt" in the dump
10238 # both destructors are not presented in the v-table
10239 next;
10240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010241 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010242 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 }
10245}
10246
10247sub registerOverriding($)
10248{
10249 my $LibVersion = $_[0];
10250 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010251 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 foreach my $ClassName (@Classes)
10253 {
10254 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10255 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010256 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10257 { # pure virtuals
10258 next;
10259 }
10260 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10261 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010262 {
10263 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10264 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10265 { # both overridden virtual methods
10266 # and implemented pure virtual methods
10267 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10268 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10269 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010271 }
10272 }
10273 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10274 delete($VirtualTable{$LibVersion}{$ClassName});
10275 }
10276 }
10277}
10278
10279sub setVirtFuncPositions($)
10280{
10281 my $LibVersion = $_[0];
10282 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10283 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010284 my ($Num, $Rel) = (1, 0);
10285
10286 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010288 if($UsedDump{$LibVersion}{"DWARF"}) {
10289 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10290 }
10291 else {
10292 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10293 }
10294 foreach my $VirtFunc (@Funcs)
10295 {
10296 if($UsedDump{$LibVersion}{"DWARF"}) {
10297 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10298 }
10299 else {
10300 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10301 }
10302
10303 # set relative positions
10304 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10305 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10306 { # relative position excluding added and removed virtual functions
10307 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10308 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10309 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010313 }
10314 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010315 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010316 {
10317 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010318 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010319 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010320 }
10321 }
10322}
10323
10324sub get_sub_classes($$$)
10325{
10326 my ($ClassId, $LibVersion, $Recursive) = @_;
10327 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10328 my @Subs = ();
10329 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10330 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010331 if($Recursive)
10332 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10334 push(@Subs, $SubSubId);
10335 }
10336 }
10337 push(@Subs, $SubId);
10338 }
10339 return @Subs;
10340}
10341
10342sub get_base_classes($$$)
10343{
10344 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010345 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010346 return () if(not defined $ClassType{"Base"});
10347 my @Bases = ();
10348 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10349 keys(%{$ClassType{"Base"}}))
10350 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010351 if($Recursive)
10352 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10354 push(@Bases, $SubBaseId);
10355 }
10356 }
10357 push(@Bases, $BaseId);
10358 }
10359 return @Bases;
10360}
10361
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010362sub getVTable_Model($$)
10363{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010364 my ($ClassId, $LibVersion) = @_;
10365 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10366 my @Elements = ();
10367 foreach my $BaseId (@Bases, $ClassId)
10368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010369 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010370 {
10371 if(defined $VirtualTable{$LibVersion}{$BName})
10372 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010373 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10374 if($UsedDump{$LibVersion}{"DWARF"}) {
10375 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10376 }
10377 else {
10378 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10379 }
10380 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010381 push(@Elements, $VFunc);
10382 }
10383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384 }
10385 }
10386 return @Elements;
10387}
10388
10389sub getVShift($$)
10390{
10391 my ($ClassId, $LibVersion) = @_;
10392 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10393 my $VShift = 0;
10394 foreach my $BaseId (@Bases)
10395 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010396 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010397 {
10398 if(defined $VirtualTable{$LibVersion}{$BName}) {
10399 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401 }
10402 }
10403 return $VShift;
10404}
10405
10406sub getShift($$)
10407{
10408 my ($ClassId, $LibVersion) = @_;
10409 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10410 my $Shift = 0;
10411 foreach my $BaseId (@Bases)
10412 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010413 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010414 {
10415 if($Size!=1)
10416 { # not empty base class
10417 $Shift+=$Size;
10418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010419 }
10420 }
10421 return $Shift;
10422}
10423
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010424sub getVTable_Size($$)
10425{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427 my $Size = 0;
10428 # three approaches
10429 if(not $Size)
10430 { # real size
10431 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10432 $Size = keys(%VTable);
10433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010434 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010435 if(not $Size)
10436 { # shared library symbol size
10437 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10438 $Size /= $WORD_SIZE{$LibVersion};
10439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010441 if(not $Size)
10442 { # model size
10443 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10444 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10445 }
10446 }
10447 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448}
10449
10450sub isCopyingClass($$)
10451{
10452 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010453 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010454}
10455
10456sub isLeafClass($$)
10457{
10458 my ($ClassId, $LibVersion) = @_;
10459 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10460}
10461
10462sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010463{ # check structured type for public fields
10464 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465}
10466
10467sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010468{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469 my ($TypePtr, $Skip, $Start, $End) = @_;
10470 return 0 if(not $TypePtr);
10471 if($End==-1) {
10472 $End = keys(%{$TypePtr->{"Memb"}})-1;
10473 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010474 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 {
10476 if($Skip and $Skip->{$MemPos})
10477 { # skip removed/added fields
10478 next;
10479 }
10480 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10481 {
10482 if(isPublic($TypePtr, $MemPos)) {
10483 return ($MemPos+1);
10484 }
10485 }
10486 }
10487 return 0;
10488}
10489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010490sub isReserved($)
10491{ # reserved fields == private
10492 my $MName = $_[0];
10493 if($MName=~/reserved|padding|f_spare/i) {
10494 return 1;
10495 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010496 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 return 1;
10498 }
10499 if($MName=~/(pad\d+)/i) {
10500 return 1;
10501 }
10502 return 0;
10503}
10504
10505sub isPublic($$)
10506{
10507 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010509 return 0 if(not $TypePtr);
10510 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10511 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010512
10513 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10514 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010516 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010518
10519 # by name in C language
10520 # TODO: add other methods to detect private members
10521 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010522 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010523 { # C-styled private data
10524 return 0;
10525 }
10526 if(lc($MName) eq "abi")
10527 { # ABI information/reserved field
10528 return 0;
10529 }
10530 if(isReserved($MName))
10531 { # reserved fields
10532 return 0;
10533 }
10534
10535 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536}
10537
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010538sub getVTable_Real($$)
10539{
10540 my ($ClassName, $LibVersion) = @_;
10541 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10542 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010543 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 if(defined $Type{"VTable"}) {
10545 return %{$Type{"VTable"}};
10546 }
10547 }
10548 return ();
10549}
10550
10551sub cmpVTables($)
10552{
10553 my $ClassName = $_[0];
10554 my $Res = cmpVTables_Real($ClassName, 1);
10555 if($Res==-1) {
10556 $Res = cmpVTables_Model($ClassName);
10557 }
10558 return $Res;
10559}
10560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561sub cmpVTables_Model($)
10562{
10563 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 return 1;
10568 }
10569 }
10570 return 0;
10571}
10572
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574{
10575 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10577 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010578 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 my %VTable_Old = getVTable_Real($ClassName, 1);
10580 my %VTable_New = getVTable_Real($ClassName, 2);
10581 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010583 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010585 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10587 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010592 my $Entry1 = $VTable_Old{$Offset};
10593 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010597 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 $Entry1 = simpleVEntry($Entry1);
10600 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010601
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010602 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010603 { # NOTE: problem with vtable-dumper
10604 next;
10605 }
10606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010607 if($Entry1 ne $Entry2)
10608 { # register as changed
10609 if($Entry1=~/::([^:]+)\Z/)
10610 {
10611 my $M1 = $1;
10612 if($Entry2=~/::([^:]+)\Z/)
10613 {
10614 my $M2 = $1;
10615 if($M1 eq $M2)
10616 { # overridden
10617 next;
10618 }
10619 }
10620 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010621 if(differentDumps("G"))
10622 {
10623 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10624 {
10625 # GCC 4.6.1: -0x00000000000000010
10626 # GCC 4.7.0: -16
10627 next;
10628 }
10629 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010630 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 }
10632 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010633 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010634}
10635
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010637{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010638 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10640 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010641 my $ClassId = $TName_Tid{1}{$ClassName};
10642 if(isPrivateABI($ClassId, 1)) {
10643 next;
10644 }
10645
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010646 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 { # already registered
10648 next;
10649 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010650 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010652 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 foreach my $Symbol (@Affected)
10654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 "Target"=>$ClassName);
10658 }
10659 }
10660 }
10661}
10662
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010663sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010664{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010665 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010666 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010667 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010668 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010670
10671 if(isPrivateABI($ClassId, 1)) {
10672 next;
10673 }
10674
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010675 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010678 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010679 if($TName_Tid{1}{$ClassName}
10680 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010681 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010682 if(defined $CompleteSignature{1}{$Symbol}
10683 and $CompleteSignature{1}{$Symbol}{"Virt"})
10684 { # override some method in v.1
10685 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010686 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010687 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 }
10689 }
10690 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010691 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010694 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 if($TName_Tid{2}{$ClassName}
10696 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010697 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010698 if(defined $CompleteSignature{2}{$Symbol}
10699 and $CompleteSignature{2}{$Symbol}{"Virt"})
10700 { # override some method in v.2
10701 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010702 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010703 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 }
10705 }
10706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010707 if($Level eq "Binary")
10708 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010709 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010710 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10711 { # check replacements, including pure virtual methods
10712 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10713 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010715 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10716 if($AddedPos==$RemovedPos)
10717 {
10718 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10719 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10720 last; # other methods will be reported as "added" or "removed"
10721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010723 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10724 {
10725 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10726 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 next;
10728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010729 my $ProblemType = "Virtual_Replacement";
10730 my @Affected = ($RemovedVFunc);
10731 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10732 { # pure methods
10733 if(not isUsedClass($ClassId, 1, $Level))
10734 { # not a parameter of some exported method
10735 next;
10736 }
10737 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010738
10739 # affected all methods (both virtual and non-virtual ones)
10740 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10741 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010743 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010744 foreach my $AffectedInt (@Affected)
10745 {
10746 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10747 { # affected exported methods only
10748 next;
10749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010750 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10751 next;
10752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10754 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010755 "Target"=>get_Signature($AddedVFunc, 2),
10756 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010758 }
10759 }
10760 }
10761 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010762 if(not checkDump(1, "2.0")
10763 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010764 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010765 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 return;
10767 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010768 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010770 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010771 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010772
10773 if(isPrivateABI($ClassId_Old, 1)) {
10774 next;
10775 }
10776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010777 if(not isCreatable($ClassId_Old, 1))
10778 { # skip classes without public constructors (including auto-generated)
10779 # example: class has only a private exported or private inline constructor
10780 next;
10781 }
10782 if($ClassName=~/>/)
10783 { # skip affected template instances
10784 next;
10785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010786 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010787 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010788 if(not $ClassId_New) {
10789 next;
10790 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010791 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010792 if($Class_New{"Type"}!~/Class|Struct/)
10793 { # became typedef
10794 if($Level eq "Binary") {
10795 next;
10796 }
10797 if($Level eq "Source")
10798 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010799 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010800 if($Class_New{"Type"}!~/Class|Struct/) {
10801 next;
10802 }
10803 $ClassId_New = $Class_New{"Tid"};
10804 }
10805 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010806
10807 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10808 { # incomplete info in the ABI dump
10809 next;
10810 }
10811
10812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010813 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10814 my @Bases_New = sort {$Class_New{"Base"}{$a}{"pos"}<=>$Class_New{"Base"}{$b}{"pos"}} keys(%{$Class_New{"Base"}});
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010815
10816 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10817 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010819 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010820 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10821 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010822 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10823 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 my $Shift_Old = getShift($ClassId_Old, 1);
10825 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010826 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010827 my ($Added, $Removed) = (0, 0);
10828 my @StableBases_Old = ();
10829 foreach my $BaseId (@Bases_Old)
10830 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010831 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010832 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010833 push(@StableBases_Old, $BaseId);
10834 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010836 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 { # removed base
10838 # excluding namespace::SomeClass to SomeClass renaming
10839 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010840 if($Level eq "Binary")
10841 { # Binary-level
10842 if($Shift_Old ne $Shift_New)
10843 { # affected fields
10844 if(havePubFields(\%Class_Old)) {
10845 $ProblemKind .= "_And_Shift";
10846 }
10847 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10848 $ProblemKind .= "_And_Size";
10849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010850 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010851 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10852 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 { # affected v-table
10854 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010855 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
10857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010858 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10860 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10862 {
10863 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10864 if($ProblemKind=~/VTable/) {
10865 $VTableChanged_M{$SubName}=1;
10866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 }
10868 }
10869 foreach my $Interface (@Affected)
10870 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010871 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10872 next;
10873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010875 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 "Target"=>$BaseName,
10877 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10878 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10879 "Shift"=>abs($Shift_New-$Shift_Old) );
10880 }
10881 $Removed+=1;
10882 }
10883 }
10884 my @StableBases_New = ();
10885 foreach my $BaseId (@Bases_New)
10886 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010887 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010888 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010889 push(@StableBases_New, $BaseId);
10890 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010891 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010892 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 { # added base
10894 # excluding namespace::SomeClass to SomeClass renaming
10895 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 if($Level eq "Binary")
10897 { # Binary-level
10898 if($Shift_Old ne $Shift_New)
10899 { # affected fields
10900 if(havePubFields(\%Class_Old)) {
10901 $ProblemKind .= "_And_Shift";
10902 }
10903 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10904 $ProblemKind .= "_And_Size";
10905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010906 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010907 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10908 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 { # affected v-table
10910 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010911 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010912 }
10913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010914 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10916 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010917 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10918 {
10919 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10920 if($ProblemKind=~/VTable/) {
10921 $VTableChanged_M{$SubName}=1;
10922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
10924 }
10925 foreach my $Interface (@Affected)
10926 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010927 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10928 next;
10929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010931 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 "Target"=>$BaseName,
10933 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10934 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10935 "Shift"=>abs($Shift_New-$Shift_Old) );
10936 }
10937 $Added+=1;
10938 }
10939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 if($Level eq "Binary")
10941 { # Binary-level
10942 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010943 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10944 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010945 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010947 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010948 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010949 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10951 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 if($NewPos!=$OldPos)
10953 { # changed position of the base class
10954 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010955 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010956 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10957 next;
10958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010959 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10960 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010961 "Target"=>$BaseName,
10962 "Old_Value"=>$OldPos-1,
10963 "New_Value"=>$NewPos-1 );
10964 }
10965 }
10966 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10967 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10968 { # became non-virtual base
10969 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10970 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010971 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10972 next;
10973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10975 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 "Target"=>$BaseName );
10977 }
10978 }
10979 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10980 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10981 { # became virtual base
10982 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10983 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010984 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10985 next;
10986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10988 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 "Target"=>$BaseName );
10990 }
10991 }
10992 }
10993 }
10994 # detect size changes in base classes
10995 if($Shift_Old!=$Shift_New)
10996 { # size of allocable class
10997 foreach my $BaseId (@StableBases_Old)
10998 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010999 my %BaseType = get_Type($BaseId, 1);
11000 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011001 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 if($Size_Old ne $Size_New
11003 and $Size_Old and $Size_New)
11004 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011005 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011006 if(isCopyingClass($BaseId, 1)) {
11007 $ProblemType = "Size_Of_Copying_Class";
11008 }
11009 elsif($AllocableClass{1}{$BaseType{"Name"}})
11010 {
11011 if($Size_New>$Size_Old)
11012 { # increased size
11013 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 else
11016 { # decreased size
11017 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11018 if(not havePubFields(\%Class_Old))
11019 { # affected class has no public members
11020 next;
11021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011023 }
11024 next if(not $ProblemType);
11025 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11026 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011027 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11028 next;
11029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11031 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 "Target"=>$BaseType{"Name"},
11033 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11034 "New_Size"=>$Size_New*$BYTE_SIZE );
11035 }
11036 }
11037 }
11038 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011039 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011040 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011041 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 { # compare virtual tables size in base classes
11043 my $VShift_Old = getVShift($ClassId_Old, 1);
11044 my $VShift_New = getVShift($ClassId_New, 2);
11045 if($VShift_Old ne $VShift_New)
11046 { # changes in the base class or changes in the list of base classes
11047 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11048 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11049 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011050 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011051 foreach my $BaseId (@AllBases_Old)
11052 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011053 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011054 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 { # lost base
11056 next;
11057 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11059 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011060 if($VSize_Old!=$VSize_New)
11061 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011062 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011063 { # TODO: affected non-virtual methods?
11064 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11066 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011068 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069 { # skip interfaces that have not changed the absolute virtual position
11070 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011071 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011072 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11073 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011074 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011075 $VTableChanged_M{$BaseType{"Name"}} = 1;
11076 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11078 { # the reason of the layout change: added virtual functions
11079 next if($VirtualReplacement{$VirtFunc});
11080 my $ProblemType = "Added_Virtual_Method";
11081 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11082 $ProblemType = "Added_Pure_Virtual_Method";
11083 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011084 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011085 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Target"=>get_Signature($VirtFunc, 2) );
11087 }
11088 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11089 { # the reason of the layout change: removed virtual functions
11090 next if($VirtualReplacement{$VirtFunc});
11091 my $ProblemType = "Removed_Virtual_Method";
11092 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11093 $ProblemType = "Removed_Pure_Virtual_Method";
11094 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011095 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011096 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011097 "Target"=>get_Signature($VirtFunc, 1) );
11098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 }
11100 }
11101 }
11102 }
11103 }
11104 }
11105 }
11106}
11107
11108sub isCreatable($$)
11109{
11110 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011111 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 or isCopyingClass($ClassId, $LibVersion)) {
11113 return 1;
11114 }
11115 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11116 { # Fix for incomplete data: if this class has
11117 # a base class then it should also has a constructor
11118 return 1;
11119 }
11120 if($ReturnedClass{$LibVersion}{$ClassId})
11121 { # returned by some method of this class
11122 # or any other class
11123 return 1;
11124 }
11125 return 0;
11126}
11127
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011128sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011130 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11132 { # parameter of some exported method
11133 return 1;
11134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011135 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11136 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011137 { # method from target class
11138 return 1;
11139 }
11140 return 0;
11141}
11142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011143sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 # - virtual
11148 # - pure-virtual
11149 # - non-virtual
11150 if($CompleteSignature{1}{$Interface}{"Data"})
11151 { # global data is not affected
11152 return;
11153 }
11154 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 if(not $Class_Id) {
11156 return;
11157 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011158 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011159 if(cmpVTables_Real($CName, 1)==0)
11160 { # no changes
11161 return;
11162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 $CheckedTypes{$Level}{$CName} = 1;
11164 if($Level eq "Binary")
11165 { # Binary-level
11166 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11167 and not isUsedClass($Class_Id, 1, $Level))
11168 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011169 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011172 }
11173 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11174 {
11175 if(defined $VirtualTable{2}{$CName}{$Func}
11176 and defined $CompleteSignature{2}{$Func})
11177 {
11178 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11179 and $CompleteSignature{2}{$Func}{"PureVirt"})
11180 { # became pure virtual
11181 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11182 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011183 "Target"=>get_Signature_M($Func, 1) );
11184 $VTableChanged_M{$CName} = 1;
11185 }
11186 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11187 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11188 { # became non-pure virtual
11189 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11190 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011191 "Target"=>get_Signature_M($Func, 1) );
11192 $VTableChanged_M{$CName} = 1;
11193 }
11194 }
11195 }
11196 if($Level eq "Binary")
11197 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 # check virtual table structure
11199 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11200 {
11201 next if($Interface eq $AddedVFunc);
11202 next if($VirtualReplacement{$AddedVFunc});
11203 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11204 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11205 { # pure virtual methods affect all others (virtual and non-virtual)
11206 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011207 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011208 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011209 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011210 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011211 elsif(not defined $VirtualTable{1}{$CName}
11212 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011214 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011215 { # became polymorphous class, added v-table pointer
11216 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 }
11221 else
11222 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011223 my $VSize_Old = getVTable_Size($CName, 1);
11224 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011225 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 if(isCopyingClass($Class_Id, 1))
11227 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11228 my $ProblemType = "Added_Virtual_Method";
11229 if(isLeafClass($Class_Id, 1)) {
11230 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11231 }
11232 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11233 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011235 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011236 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 else
11238 {
11239 my $ProblemType = "Added_Virtual_Method";
11240 if(isLeafClass($Class_Id, 1)) {
11241 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11242 }
11243 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11244 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011246 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011248 }
11249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11251 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011252 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 if(defined $VirtualTable{1}{$CName}
11254 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011256 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11257 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011258
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011259 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011260 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011261 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11262 foreach my $ASymbol (@Affected)
11263 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011264 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11265 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011266 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011267 next;
11268 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011269 }
11270 $CheckedSymbols{$Level}{$ASymbol} = 1;
11271 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11272 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011273 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 }
11278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011279 else {
11280 # safe
11281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011283 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11284 {
11285 next if($VirtualReplacement{$RemovedVFunc});
11286 if($RemovedVFunc eq $Interface
11287 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11288 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011289 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011290 next;
11291 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011292 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 { # became non-polymorphous class, removed v-table pointer
11294 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11295 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011296 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011297 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011298 }
11299 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11300 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11301 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011303 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011304 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11305 next;
11306 }
11307 my $VPos_New = -1;
11308 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011309 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011310 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11311 }
11312 else
11313 {
11314 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011315 next;
11316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011317 }
11318 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11319 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11320 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11321 {
11322 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11323 foreach my $ASymbol (@Affected)
11324 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011325 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011327 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011328 next;
11329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011330 }
11331 my $ProblemType = "Removed_Virtual_Method";
11332 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11333 $ProblemType = "Removed_Pure_Virtual_Method";
11334 }
11335 $CheckedSymbols{$Level}{$ASymbol} = 1;
11336 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11337 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011338 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011339 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011341 }
11342 }
11343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 }
11345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011346 else
11347 { # Source-level
11348 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011350 next if($Interface eq $AddedVFunc);
11351 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011353 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11354 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011355 "Target"=>get_Signature($AddedVFunc, 2) );
11356 }
11357 }
11358 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11359 {
11360 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11361 {
11362 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11363 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011364 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
11366 }
11367 }
11368}
11369
11370sub find_MemberPair_Pos_byName($$)
11371{
11372 my ($Member_Name, $Pair_Type) = @_;
11373 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11374 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11375 {
11376 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11377 {
11378 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11379 $Name=~s/\A[_]+|[_]+\Z//g;
11380 if($Name eq $Member_Name) {
11381 return $MemberPair_Pos;
11382 }
11383 }
11384 }
11385 return "lost";
11386}
11387
11388sub find_MemberPair_Pos_byVal($$)
11389{
11390 my ($Member_Value, $Pair_Type) = @_;
11391 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11392 {
11393 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11394 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11395 return $MemberPair_Pos;
11396 }
11397 }
11398 return "lost";
11399}
11400
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011401sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011403 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011405 if( $_->{"T1"} eq $_[0]
11406 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011407 {
11408 return 1;
11409 }
11410 }
11411 return 0;
11412}
11413
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011414sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011416 my %IDs = (
11417 "T1" => $_[0],
11418 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011419 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011420 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011421}
11422
11423sub isRenamed($$$$$)
11424{
11425 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11426 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11427 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011428 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 if(not defined $Type2->{"Memb"}{$MemPos}) {
11430 return "";
11431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011432 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011433 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011434
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011435 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11436 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 if($MemberPair_Pos_Rev eq "lost")
11438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11440 { # base type match
11441 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011443 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11444 { # exact type match
11445 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011447 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11448 { # size match
11449 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011451 if(isReserved($Pair_Name))
11452 { # reserved fields
11453 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011454 }
11455 }
11456 return "";
11457}
11458
11459sub isLastElem($$)
11460{
11461 my ($Pos, $TypeRef) = @_;
11462 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011463 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011464 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11465 return 1;
11466 }
11467 elsif($Name=~/END|NLIMITS\Z/)
11468 { # __RLIMIT_NLIMITS
11469 return 1;
11470 }
11471 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11472 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11473 { # NImageFormats, NColorRoles
11474 return 1;
11475 }
11476 return 0;
11477}
11478
11479sub nonComparable($$)
11480{
11481 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011482
11483 my $N1 = $T1->{"Name"};
11484 my $N2 = $T2->{"Name"};
11485
11486 $N1=~s/\A(struct|union|enum) //;
11487 $N2=~s/\A(struct|union|enum) //;
11488
11489 if($N1 ne $N2
11490 and not isAnon($N1)
11491 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492 { # different names
11493 if($T1->{"Type"} ne "Pointer"
11494 or $T2->{"Type"} ne "Pointer")
11495 { # compare base types
11496 return 1;
11497 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011498 if($N1!~/\Avoid\s*\*/
11499 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011500 {
11501 return 1;
11502 }
11503 }
11504 elsif($T1->{"Type"} ne $T2->{"Type"})
11505 { # different types
11506 if($T1->{"Type"} eq "Class"
11507 and $T2->{"Type"} eq "Struct")
11508 { # "class" to "struct"
11509 return 0;
11510 }
11511 elsif($T2->{"Type"} eq "Class"
11512 and $T1->{"Type"} eq "Struct")
11513 { # "struct" to "class"
11514 return 0;
11515 }
11516 else
11517 { # "class" to "enum"
11518 # "union" to "class"
11519 # ...
11520 return 1;
11521 }
11522 }
11523 return 0;
11524}
11525
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011526sub isOpaque($)
11527{
11528 my $T = $_[0];
11529 if(not defined $T->{"Memb"})
11530 {
11531 return 1;
11532 }
11533 return 0;
11534}
11535
11536sub removeVPtr($)
11537{ # support for old ABI dumps
11538 my $TPtr = $_[0];
11539 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11540 if($#Pos>=1)
11541 {
11542 foreach my $Pos (0 .. $#Pos-1)
11543 {
11544 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11545 }
11546 delete($TPtr->{"Memb"}{$#Pos});
11547 }
11548}
11549
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011550sub isPrivateABI($$)
11551{
11552 my ($TypeId, $LibVersion) = @_;
11553
11554 if($CheckPrivateABI) {
11555 return 0;
11556 }
11557
11558 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11559 return 1;
11560 }
11561
11562 return 0;
11563}
11564
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011565sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011566{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011567 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011568 return {} if(not $Type1_Id or not $Type2_Id);
11569
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011570 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011571 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011572 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011574
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011575 my %Type1 = get_Type($Type1_Id, 1);
11576 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011577 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011578 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011579 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011580
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011581 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11582 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011583
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011584 if(defined $UsedDump{1}{"DWARF"})
11585 {
11586 if($Type1_Pure{"Name"} eq "__unknown__"
11587 or $Type2_Pure{"Name"} eq "__unknown__")
11588 { # Error ABI dump
11589 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11590 }
11591 }
11592
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011593 if(isPrivateABI($Type1_Id, 1)) {
11594 return {};
11595 }
11596
11597 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11598 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11599
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011600 my %SubProblems = ();
11601
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011602 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11603 {
11604 if($Type1_Pure{"Type"}=~/Struct|Union/
11605 and $Type2_Pure{"Type"}=~/Struct|Union/)
11606 {
11607 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11608 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011609 if(not defined $UsedDump{1}{"DWARF"}
11610 and not defined $UsedDump{2}{"DWARF"})
11611 {
11612 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11613 "Target"=>$Type1_Pure{"Name"},
11614 "Type_Name"=>$Type1_Pure{"Name"} );
11615 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011616
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011617 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011618 }
11619 }
11620 }
11621
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011622 if(not $Type1_Pure{"Size"}
11623 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011624 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011625 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11626 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11627 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011628 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011630 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011631 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011632 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011633 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011635 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11636 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11637 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011638
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011639 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11640 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011641 }
11642
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011643 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11644 { # support for old ABI dumps
11645 # _vptr field added in 3.0
11646 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11647 {
11648 if(defined $Type2_Pure{"Memb"}
11649 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11650 {
11651 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11652 delete($Type2_Pure{"Memb"}{0});
11653 }
11654 else {
11655 removeVPtr(\%Type2_Pure);
11656 }
11657 }
11658 }
11659 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11660 {
11661 if(defined $Type1_Pure{"Memb"}
11662 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11663 {
11664 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11665 delete($Type1_Pure{"Memb"}{0});
11666 }
11667 else {
11668 removeVPtr(\%Type1_Pure);
11669 }
11670 }
11671 }
11672 }
11673
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011674 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11675 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011676
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011677 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011678 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11679 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011680 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011681 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11682 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011683 if($Base_1{"Name"} ne $Base_2{"Name"})
11684 {
11685 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011686 or differentDumps("V")
11687 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011688 { # different GCC versions or different dumps
11689 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11690 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11691 # std::__va_list and __va_list
11692 $Base_1{"Name"}=~s/\A(\w+::)+//;
11693 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011694 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11695 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011697 }
11698 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11699 and $Base_1{"Name"} ne $Base_2{"Name"})
11700 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011701 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011702 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011703 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 {
11705 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11706 "Target"=>$Typedef_1{"Name"},
11707 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011708 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11709 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011711 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11712 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011713
11714 if(defined $UsedDump{1}{"DWARF"})
11715 {
11716 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11717 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11718 { # Error ABI dump
11719 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11720 }
11721 }
11722
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011723 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011724 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011725 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11726 {
11727 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11728 "Target"=>$Typedef_1{"Name"},
11729 "Type_Name"=>$Typedef_1{"Name"},
11730 "Old_Value"=>$Base_1{"Name"},
11731 "New_Value"=>$Base_2{"Name"} );
11732 }
11733 else
11734 {
11735 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11736 "Target"=>$Typedef_1{"Name"},
11737 "Type_Name"=>$Typedef_1{"Name"},
11738 "Old_Value"=>$Base_1{"Name"},
11739 "New_Value"=>$Base_2{"Name"} );
11740 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011742 }
11743 }
11744 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11745 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011746 my $TT1 = $Type1_Pure{"Type"};
11747 my $TT2 = $Type2_Pure{"Type"};
11748
11749 if($TT1 ne $TT2
11750 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011752 my $Short1 = $Type1_Pure{"Name"};
11753 my $Short2 = $Type2_Pure{"Name"};
11754
11755 $Short1=~s/\A\Q$TT1\E //ig;
11756 $Short2=~s/\A\Q$TT2\E //ig;
11757
11758 if($Short1 eq $Short2)
11759 {
11760 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11761 "Target"=>$Type1_Pure{"Name"},
11762 "Type_Name"=>$Type1_Pure{"Name"},
11763 "Old_Value"=>lc($Type1_Pure{"Type"}),
11764 "New_Value"=>lc($Type2_Pure{"Type"}) );
11765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011767 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011768 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011769
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011770 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11773 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11774 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11775 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011776 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011777 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011778 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 {
11780 my $ProblemKind = "DataType_Size";
11781 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011782 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 {
11784 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11785 $ProblemKind = "Size_Of_Copying_Class";
11786 }
11787 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11788 {
11789 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11790 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011792 else
11793 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 # descreased size of allocable class
11795 # it has no special effects
11796 }
11797 }
11798 }
11799 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11800 "Target"=>$Type1_Pure{"Name"},
11801 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011803 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 }
11805 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011806 if(defined $Type1_Pure{"BaseType"}
11807 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011808 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011809 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11810 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011811 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011812 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11813 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011814 }
11815 }
11816 }
11817 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11818 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11819 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11820 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11821 { # detect removed and renamed fields
11822 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11823 next if(not $Member_Name);
11824 my $MemberPair_Pos = (defined $Type2_Pure{"Memb"}{$Member_Pos} and $Type2_Pure{"Memb"}{$Member_Pos}{"name"} eq $Member_Name)?$Member_Pos:find_MemberPair_Pos_byName($Member_Name, \%Type2_Pure);
11825 if($MemberPair_Pos eq "lost")
11826 {
11827 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11828 {
11829 if(isUnnamed($Member_Name))
11830 { # support for old-version dumps
11831 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011832 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011833 next;
11834 }
11835 }
11836 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11837 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011838 $RenamedField{$Member_Pos} = $RenamedTo;
11839 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 }
11841 else
11842 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011843 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 }
11845 }
11846 elsif($Type1_Pure{"Type"} eq "Enum")
11847 {
11848 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11849 next if($Member_Value1 eq "");
11850 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11851 if($MemberPair_Pos ne "lost")
11852 { # renamed
11853 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11854 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11855 if($MemberPair_Pos_Rev eq "lost")
11856 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011857 $RenamedField{$Member_Pos} = $RenamedTo;
11858 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 }
11860 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011861 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 }
11863 }
11864 else
11865 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011866 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011867 }
11868 }
11869 }
11870 else
11871 { # related
11872 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11873 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11874 }
11875 }
11876 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11877 { # detect added fields
11878 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11879 next if(not $Member_Name);
11880 my $MemberPair_Pos = (defined $Type1_Pure{"Memb"}{$Member_Pos} and $Type1_Pure{"Memb"}{$Member_Pos}{"name"} eq $Member_Name)?$Member_Pos:find_MemberPair_Pos_byName($Member_Name, \%Type1_Pure);
11881 if($MemberPair_Pos eq "lost")
11882 {
11883 if(isUnnamed($Member_Name))
11884 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011885 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011886 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011887 next;
11888 }
11889 }
11890 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11891 {
11892 if(not $RenamedField_Rev{$Member_Pos})
11893 { # added
11894 $AddedField{$Member_Pos}=1;
11895 }
11896 }
11897 }
11898 }
11899 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11900 { # detect moved fields
11901 my (%RelPos, %RelPosName, %AbsPos) = ();
11902 my $Pos = 0;
11903 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11904 { # relative positions in 1st version
11905 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11906 next if(not $Member_Name);
11907 if(not $RemovedField{$Member_Pos})
11908 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011909 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011910 $RelPosName{1}{$Pos} = $Member_Name;
11911 $AbsPos{1}{$Pos++} = $Member_Pos;
11912 }
11913 }
11914 $Pos = 0;
11915 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11916 { # relative positions in 2nd version
11917 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11918 next if(not $Member_Name);
11919 if(not $AddedField{$Member_Pos})
11920 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011921 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 $RelPosName{2}{$Pos} = $Member_Name;
11923 $AbsPos{2}{$Pos++} = $Member_Pos;
11924 }
11925 }
11926 foreach my $Member_Name (keys(%{$RelPos{1}}))
11927 {
11928 my $RPos1 = $RelPos{1}{$Member_Name};
11929 my $AbsPos1 = $NameToPosA{$Member_Name};
11930 my $Member_Name2 = $Member_Name;
11931 if(my $RenamedTo = $RenamedField{$AbsPos1})
11932 { # renamed
11933 $Member_Name2 = $RenamedTo;
11934 }
11935 my $RPos2 = $RelPos{2}{$Member_Name2};
11936 if($RPos2 ne "" and $RPos1 ne $RPos2)
11937 { # different relative positions
11938 my $AbsPos2 = $NameToPosB{$Member_Name2};
11939 if($AbsPos1 ne $AbsPos2)
11940 { # different absolute positions
11941 my $ProblemType = "Moved_Field";
11942 if(not isPublic(\%Type1_Pure, $AbsPos1))
11943 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011944 if($Level eq "Source") {
11945 next;
11946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011947 $ProblemType = "Moved_Private_Field";
11948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011949 if($Level eq "Binary"
11950 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011952 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011954 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 if($MemSize1 ne $MemSize2) {
11956 $ProblemType .= "_And_Size";
11957 }
11958 }
11959 if($ProblemType eq "Moved_Private_Field") {
11960 next;
11961 }
11962 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11963 "Target"=>$Member_Name,
11964 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 "Old_Value"=>$RPos1,
11966 "New_Value"=>$RPos2 );
11967 }
11968 }
11969 }
11970 }
11971 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011972 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011973 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11974 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011975 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 if(my $RenamedTo = $RenamedField{$Member_Pos})
11977 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011978 if(defined $Constants{2}{$Member_Name})
11979 {
11980 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11981 { # define OLD NEW
11982 next; # Safe
11983 }
11984 }
11985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011986 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11987 {
11988 if(isPublic(\%Type1_Pure, $Member_Pos))
11989 {
11990 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11991 "Target"=>$Member_Name,
11992 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011993 "Old_Value"=>$Member_Name,
11994 "New_Value"=>$RenamedTo );
11995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011996 elsif(isReserved($Member_Name))
11997 {
11998 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11999 "Target"=>$Member_Name,
12000 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012001 "Old_Value"=>$Member_Name,
12002 "New_Value"=>$RenamedTo );
12003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 }
12005 elsif($Type1_Pure{"Type"} eq "Enum")
12006 {
12007 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
12008 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
12009 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012010 "Old_Value"=>$Member_Name,
12011 "New_Value"=>$RenamedTo );
12012 }
12013 }
12014 elsif($RemovedField{$Member_Pos})
12015 { # removed
12016 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12017 {
12018 my $ProblemType = "Removed_Field";
12019 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012020 or isUnnamed($Member_Name))
12021 {
12022 if($Level eq "Source") {
12023 next;
12024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012025 $ProblemType = "Removed_Private_Field";
12026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012027 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012029 {
12030 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
12031 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012032 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012033 { # changed offset
12034 $ProblemType .= "_And_Layout";
12035 }
12036 }
12037 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
12038 { # affected size
12039 $ProblemType .= "_And_Size";
12040 }
12041 }
12042 if($ProblemType eq "Removed_Private_Field") {
12043 next;
12044 }
12045 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12046 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012047 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 }
12049 elsif($Type2_Pure{"Type"} eq "Union")
12050 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012051 if($Level eq "Binary"
12052 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053 {
12054 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12055 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012056 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 }
12058 else
12059 {
12060 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12061 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012062 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 }
12064 }
12065 elsif($Type1_Pure{"Type"} eq "Enum")
12066 {
12067 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12068 "Target"=>$Member_Name,
12069 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 "Old_Value"=>$Member_Name );
12071 }
12072 }
12073 else
12074 { # changed
12075 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12076 if($Type1_Pure{"Type"} eq "Enum")
12077 {
12078 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12079 next if($Member_Value1 eq "");
12080 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12081 next if($Member_Value2 eq "");
12082 if($Member_Value1 ne $Member_Value2)
12083 {
12084 my $ProblemType = "Enum_Member_Value";
12085 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12086 $ProblemType = "Enum_Last_Member_Value";
12087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012088 if($SkipConstants{1}{$Member_Name}) {
12089 $ProblemType = "Enum_Private_Member_Value";
12090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012091 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12092 "Target"=>$Member_Name,
12093 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 "Old_Value"=>$Member_Value1,
12095 "New_Value"=>$Member_Value2 );
12096 }
12097 }
12098 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12099 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012100 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12101 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12102
12103 if($Access1 ne "private"
12104 and $Access2 eq "private")
12105 {
12106 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12107 "Target"=>$Member_Name,
12108 "Type_Name"=>$Type1_Pure{"Name"});
12109 }
12110 elsif($Access1 ne "protected"
12111 and $Access1 ne "private"
12112 and $Access2 eq "protected")
12113 {
12114 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12115 "Target"=>$Member_Name,
12116 "Type_Name"=>$Type1_Pure{"Name"});
12117 }
12118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12120 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012121 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012122 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12123 $SizeV1 = $BSize1;
12124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012125 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12127 $SizeV2 = $BSize2;
12128 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012129 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12130 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012131 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012132 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012133 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012134 {
12135 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12136 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12137 { # field size change (including anon-structures and unions)
12138 # - same types
12139 # - unnamed types
12140 # - bitfields
12141 my $ProblemType = "Field_Size";
12142 if(not isPublic(\%Type1_Pure, $Member_Pos)
12143 or isUnnamed($Member_Name))
12144 { # should not be accessed by applications, goes to "Low Severity"
12145 # example: "abidata" members in GStreamer types
12146 $ProblemType = "Private_".$ProblemType;
12147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012148 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012150 if($Type2_Pure{"Type"} ne "Union"
12151 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012153 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012154 { # changed offset
12155 $ProblemType .= "_And_Layout";
12156 }
12157 }
12158 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12159 $ProblemType .= "_And_Type_Size";
12160 }
12161 }
12162 if($ProblemType eq "Private_Field_Size")
12163 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012164 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012165 if($ProblemType eq "Field_Size")
12166 {
12167 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12168 { # Low severity
12169 $ProblemType = "Struct_Field_Size_Increased";
12170 }
12171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012172 if($ProblemType)
12173 { # register a problem
12174 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12175 "Target"=>$Member_Name,
12176 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 "Old_Size"=>$SizeV1,
12178 "New_Size"=>$SizeV2);
12179 }
12180 }
12181 }
12182 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12183 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12184 { # do NOT check bitfield type changes
12185 next;
12186 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012187 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012188 {
12189 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12190 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12191 {
12192 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12193 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012194 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012195 }
12196 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12197 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12198 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012200 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012201 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012202 }
12203 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012204 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12205 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012206 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012207 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12208 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012209
12210 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012212 or $ProblemType eq "Field_Type_And_Size"
12213 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012214 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012215 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012216 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012217 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012218 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012219 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012220 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012221 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012222 }
12223 }
12224 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12225 {
12226 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012227 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012228 }
12229 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012230 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012231 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012232 }
12233 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12234 {
12235 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012236 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012237 }
12238 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012240 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012241 }
12242 }
12243 }
12244
12245 if($Level eq "Source")
12246 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012247 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012248 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012249 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12250 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012251
12252 if($ProblemType eq "Field_Type")
12253 {
12254 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012255 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
12257 }
12258 }
12259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012260
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012261 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 {
12263 my $ProblemType_Init = $ProblemType;
12264 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012265 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 if(not isPublic(\%Type1_Pure, $Member_Pos)
12267 or isUnnamed($Member_Name)) {
12268 $ProblemType = "Private_".$ProblemType;
12269 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012270 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012272 if($Type2_Pure{"Type"} ne "Union"
12273 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012274 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012275 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276 { # changed offset
12277 $ProblemType .= "_And_Layout";
12278 }
12279 }
12280 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12281 $ProblemType .= "_And_Type_Size";
12282 }
12283 }
12284 }
12285 else
12286 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012287 # TODO: Private_Field_Type rule?
12288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 if(not isPublic(\%Type1_Pure, $Member_Pos)
12290 or isUnnamed($Member_Name)) {
12291 next;
12292 }
12293 }
12294 if($ProblemType eq "Private_Field_Type_And_Size")
12295 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 }
12297 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12298 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012299 "Type_Name"=>$Type1_Pure{"Name"});
12300
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012301 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012303 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
12305 }
12306 if(not isPublic(\%Type1_Pure, $Member_Pos))
12307 { # do NOT check internal type changes
12308 next;
12309 }
12310 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012311 { # checking member type changes
12312 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12313
12314 my %DupProblems = ();
12315
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012316 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012318 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012319 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012320 if(not defined $AllAffected)
12321 {
12322 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12323 next;
12324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012326
12327 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12328 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12329
12330 if(not defined $AllAffected)
12331 {
12332 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 }
12334 }
12335 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012336
12337 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 }
12339 }
12340 }
12341 }
12342 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12343 { # checking added members, public and private
12344 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12345 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012346 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 if($AddedField{$Member_Pos})
12348 { # added
12349 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12350 {
12351 my $ProblemType = "Added_Field";
12352 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012353 or isUnnamed($Member_Name))
12354 {
12355 if($Level eq "Source") {
12356 next;
12357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 $ProblemType = "Added_Private_Field";
12359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012360 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012361 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012362 {
12363 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12364 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012365 if(getOffset($MNum-1, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2})!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012366 { # changed offset
12367 $ProblemType .= "_And_Layout";
12368 }
12369 }
12370 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12371 $ProblemType .= "_And_Size";
12372 }
12373 }
12374 if($ProblemType eq "Added_Private_Field")
12375 { # skip added private fields
12376 next;
12377 }
12378 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12379 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012380 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381 }
12382 elsif($Type2_Pure{"Type"} eq "Union")
12383 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012384 if($Level eq "Binary"
12385 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 {
12387 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12388 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012389 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012390 }
12391 else
12392 {
12393 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12394 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012395 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 }
12397 }
12398 elsif($Type2_Pure{"Type"} eq "Enum")
12399 {
12400 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12401 next if($Member_Value eq "");
12402 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12403 "Target"=>$Member_Name,
12404 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012405 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406 }
12407 }
12408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012409
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012410 if($Type1_Pure{"Type"} eq "FuncPtr")
12411 {
12412 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12413 {
12414 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12415 next;
12416 }
12417
12418 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12419 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12420
12421 my $PName = "p".$PPos;
12422
12423 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12424 my %DupProblems = ();
12425
12426 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12427 {
12428 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12429 {
12430 if(not defined $AllAffected)
12431 {
12432 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12433 next;
12434 }
12435 }
12436
12437 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12438 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12439
12440 if(not defined $AllAffected)
12441 {
12442 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12443 }
12444 }
12445 }
12446
12447 %DupProblems = ();
12448 }
12449 }
12450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012452 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453}
12454
12455sub isUnnamed($) {
12456 return $_[0]=~/\Aunnamed\d+\Z/;
12457}
12458
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012459sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012460{
12461 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012462 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12463 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12464 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12465 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012467 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012468 }
12469 return $TypeName;
12470}
12471
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012472sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012474 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012475 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012476 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12477 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012478 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12480 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 return () if(not $Type{"Type"});
12482 if($Type{"Type"} ne $Type_Type)
12483 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012484 return () if(not $Type{"BaseType"});
12485 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012487 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012488 return %Type;
12489}
12490
12491my %TypeSpecAttributes = (
12492 "Const" => 1,
12493 "Volatile" => 1,
12494 "ConstVolatile" => 1,
12495 "Restrict" => 1,
12496 "Typedef" => 1
12497);
12498
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012499sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012501 my ($TypeId, $Info) = @_;
12502 if(not $TypeId or not $Info
12503 or not $Info->{$TypeId}) {
12504 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012506 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12507 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12508 }
12509 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012510 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012512 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012514 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515 return %Type;
12516}
12517
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012520 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12523 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012524 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012525 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12526 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012527 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12528 my $PLevel = 0;
12529 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12530 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012532 return $PLevel if(not $Type{"BaseType"});
12533 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12534 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12535 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536}
12537
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012538sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012539{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012540 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012542 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12543 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012544 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012545 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12546 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012547 return %Type if(not $Type{"BaseType"});
12548 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012549 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550 return %Type;
12551}
12552
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012553sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012554{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012555 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12558 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012559 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012560 my $Qual = "";
12561 if($Type{"Type"} eq "Pointer") {
12562 $Qual .= "*";
12563 }
12564 elsif($Type{"Type"} eq "Ref") {
12565 $Qual .= "&";
12566 }
12567 elsif($Type{"Type"} eq "ConstVolatile") {
12568 $Qual .= "const volatile";
12569 }
12570 elsif($Type{"Type"} eq "Const"
12571 or $Type{"Type"} eq "Volatile"
12572 or $Type{"Type"} eq "Restrict") {
12573 $Qual .= lc($Type{"Type"});
12574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012575 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 return $BQual.$Qual;
12577}
12578
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012579sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012581 my ($TypeId, $Info) = @_;
12582 if(not $TypeId or not $Info
12583 or not $Info->{$TypeId}) {
12584 return ();
12585 }
12586 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012587 return %Type if(not $Type{"BaseType"});
12588 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012589 {
12590 if($Info->{$BTid}) {
12591 return %{$Info->{$BTid}};
12592 }
12593 else { # something is going wrong
12594 return ();
12595 }
12596 }
12597 else {
12598 return %Type;
12599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600}
12601
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012602sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012605 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012606 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12607 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608}
12609
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012610sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012611{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612 my $Symbol = $_[0];
12613 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12614}
12615
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012617 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12618}
12619
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012620sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012622 my ($SInfo, $LibVersion) = @_;
12623
12624 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012625 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012626 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012628 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012629 return 1;
12630 }
12631 }
12632 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012633 if(my $ShortName = $SInfo->{"ShortName"})
12634 {
12635 if(index($ShortName,"<")!=-1
12636 and index($ShortName,">")!=-1) {
12637 return 1;
12638 }
12639 }
12640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012641 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642}
12643
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012644sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012646 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012647 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012649 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012650 { # class specialization
12651 return 1;
12652 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012653 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012654 { # method specialization
12655 return 1;
12656 }
12657 }
12658 return 0;
12659}
12660
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012661sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012663 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012664
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012665 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 { # non-public global data
12667 return 0;
12668 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012669
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012670 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012671 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012672 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012673 }
12674
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012675 if($Symbol=~/\A_Z/)
12676 {
12677 if($Symbol=~/[CD][3-4]E/) {
12678 return 0;
12679 }
12680 }
12681
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012682 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012683 { # support for old ABI dumps in --headers-only mode
12684 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12685 {
12686 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12687 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012688 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689 if(not $PType or $PType eq "Unknown") {
12690 return 0;
12691 }
12692 }
12693 }
12694 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012695 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012696 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012697 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12698
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012699 if($SkipSymbols{$LibVersion}{$Symbol})
12700 { # user defined symbols to ignore
12701 return 0;
12702 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012703
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012704 if($SymbolsListPath and not $SymbolsList{$Symbol})
12705 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012706 if(not $TargetHeadersPath or not $Header
12707 or not is_target_header($Header, 1))
12708 { # -symbols-list | -headers-list
12709 return 0;
12710 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012711 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012712
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012713 if($AppPath and not $SymbolsList_App{$Symbol})
12714 { # user defined symbols (in application)
12715 return 0;
12716 }
12717
12718 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12719
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012720 if($ClassId)
12721 {
12722 if(not isTargetType($ClassId, $LibVersion)) {
12723 return 0;
12724 }
12725 }
12726
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12728 if(not $NameSpace and $ClassId)
12729 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012730 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 }
12732 if($NameSpace)
12733 { # user defined namespaces to ignore
12734 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12735 return 0;
12736 }
12737 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12738 { # nested namespaces
12739 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12740 return 0;
12741 }
12742 }
12743 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012744 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012745 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012746 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747 { # --skip-headers or <skip_headers> (not <skip_including>)
12748 if($Skip==1) {
12749 return 0;
12750 }
12751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012752 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012753 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012754 { # user defined types
12755 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12756
12757 if(not $TypesList{$CName})
12758 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012759 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12760 {
12761 $CName=~s/\A\Q$NS\E\:\://g;
12762 }
12763
12764 if(not $TypesList{$CName})
12765 {
12766 my $Found = 0;
12767
12768 while($CName=~s/\:\:.+?\Z//)
12769 {
12770 if($TypesList{$CName})
12771 {
12772 $Found = 1;
12773 last;
12774 }
12775 }
12776
12777 if(not $Found) {
12778 return 0;
12779 }
12780 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012781 }
12782 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012783
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012784 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12785 { # non-target symbols
12786 return 0;
12787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012790 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12791 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012792 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012793 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12794 { # inline virtual methods
12795 if($Type=~/InlineVirt/) {
12796 return 1;
12797 }
12798 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12799 if(not $Allocable)
12800 { # check bases
12801 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12802 {
12803 if(not isCopyingClass($DCId, $LibVersion))
12804 { # exists a derived class without default c-tor
12805 $Allocable=1;
12806 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 }
12809 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012810 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012811 return 0;
12812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012814 else
12815 { # inline non-virtual methods
12816 return 0;
12817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012819 }
12820 }
12821 return 1;
12822}
12823
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012826 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12828 {
12829 if(link_symbol($Symbol, 1, "+Deps"))
12830 { # linker can find a new symbol
12831 # in the old-version library
12832 # So, it's not a new symbol
12833 next;
12834 }
12835 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012836 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 next;
12838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 }
12841}
12842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012843sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012845 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012846 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12847 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 if(link_symbol($Symbol, 2, "+Deps"))
12849 { # linker can find an old symbol
12850 # in the new-version library
12851 next;
12852 }
12853 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012854 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 next;
12856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012857 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012858 }
12859}
12860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012862{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012863 my $Level = $_[0];
12864 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012865 { # checking added symbols
12866 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012867 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012868 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012871 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 { # checking removed symbols
12873 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012874 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012875 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 { # skip v-tables for templates, that should not be imported by applications
12877 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012878 if(my $CName = $VTableClass{$Symbol})
12879 {
12880 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12881 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012882 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012883 next;
12884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012885 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012886
12887 if($SkipSymbols{1}{$Symbol})
12888 { # user defined symbols to ignore
12889 next;
12890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012891 }
12892 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012893 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 }
12895 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12896 { # symbols for pure virtual methods cannot be called by clients
12897 next;
12898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012899 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012900 }
12901}
12902
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012903sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012904{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012905 my ($LibVersion, $V) = @_;
12906 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12907 return $Cache{"checkDump"}{$LibVersion}{$V};
12908 }
12909 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910}
12911
12912sub detectAdded_H($)
12913{
12914 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012915 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 if($Level eq "Source")
12918 { # remove symbol version
12919 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12920 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012921
12922 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12923 { # skip artificial constructors
12924 next;
12925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12928 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929 next;
12930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012931 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012932 next;
12933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934 if(not defined $CompleteSignature{1}{$Symbol}
12935 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12936 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012937 if($UsedDump{2}{"SrcBin"})
12938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012939 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 { # support for old and different (!) ABI dumps
12941 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12942 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012944 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012945 {
12946 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12947 {
12948 if($Lang eq "C")
12949 { # support for old ABI dumps: missed extern "C" functions
12950 next;
12951 }
12952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012954 else
12955 {
12956 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012957 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012958 next;
12959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 }
12961 }
12962 }
12963 }
12964 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012965 }
12966 }
12967}
12968
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12973 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012974 if($Level eq "Source")
12975 { # remove symbol version
12976 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12977 $Symbol=$SN;
12978 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012979 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12980 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 next;
12982 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012983 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012984 next;
12985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 if(not defined $CompleteSignature{2}{$Symbol}
12987 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012988 {
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030012989 if(defined $UsedDump{1}{"DWARF"}
12990 and $Level eq "Source")
12991 {
12992 if(link_symbol($Symbol, 2, "-Deps"))
12993 { # not present in debug-info,
12994 # but present as ELF symbol
12995 next;
12996 }
12997 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012998 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012999 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013000 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013001 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013002 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
13003 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013004 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013005 if($CheckHeadersOnly)
13006 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013007 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
13008 {
13009 if($Lang eq "C")
13010 { # support for old ABI dumps: missed extern "C" functions
13011 next;
13012 }
13013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013015 else
13016 {
13017 if(not link_symbol($Symbol, 1, "-Deps"))
13018 { # skip removed inline symbols
13019 next;
13020 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013021 }
13022 }
13023 }
13024 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013025 if(not checkDump(1, "2.15"))
13026 {
13027 if($Symbol=~/_IT_E\Z/)
13028 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13029 next;
13030 }
13031 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013032 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13033 {
13034 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13035 {
13036 if(defined $Constants{2}{$Short})
13037 {
13038 my $Val = $Constants{2}{$Short}{"Value"};
13039 if(defined $Func_ShortName{2}{$Val})
13040 { # old name defined to new
13041 next;
13042 }
13043 }
13044 }
13045
13046 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013047 $RemovedInt{$Level}{$Symbol} = 1;
13048 if($Level eq "Source")
13049 { # search for a source-compatible equivalent
13050 setAlternative($Symbol, $Level);
13051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013052 }
13053 }
13054}
13055
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013056sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013057{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013058 my $Level = $_[0];
13059 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013060 { # checking added symbols
13061 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013062 next if($CompleteSignature{2}{$Symbol}{"Private"});
13063 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013064 if($Level eq "Binary")
13065 {
13066 if($CompleteSignature{2}{$Symbol}{"InLine"})
13067 {
13068 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13069 { # skip inline non-virtual functions
13070 next;
13071 }
13072 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013073 }
13074 else
13075 { # Source
13076 if($SourceAlternative_B{$Symbol}) {
13077 next;
13078 }
13079 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013080 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013081 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013082 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 { # checking removed symbols
13084 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013085 next if($CompleteSignature{1}{$Symbol}{"Private"});
13086 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013087 if($Level eq "Binary")
13088 {
13089 if($CompleteSignature{1}{$Symbol}{"InLine"})
13090 {
13091 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13092 { # skip inline non-virtual functions
13093 next;
13094 }
13095 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013096 }
13097 else
13098 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013099 if(my $Alt = $SourceAlternative{$Symbol})
13100 {
13101 if(defined $CompleteSignature{1}{$Alt}
13102 and $CompleteSignature{1}{$Symbol}{"Const"})
13103 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013104 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013105 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013106 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013107 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013108 }
13109 else
13110 { # do NOT show removed symbol
13111 next;
13112 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 }
13114 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013115 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013116 }
13117}
13118
13119sub addParamNames($)
13120{
13121 my $LibraryVersion = $_[0];
13122 return if(not keys(%AddIntParams));
13123 my $SecondVersion = $LibraryVersion==1?2:1;
13124 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13125 {
13126 next if(not keys(%{$AddIntParams{$Interface}}));
13127 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013128 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013129 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13130 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013131 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013132 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13133 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13134 {
13135 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13136 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13137 }
13138 }
13139 else {
13140 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13141 }
13142 }
13143 }
13144 }
13145}
13146
13147sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013148{ # detect changed typedefs to show
13149 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013150 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13151 {
13152 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013153 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13154 if(not $BName1 or isAnon($BName1)) {
13155 next;
13156 }
13157 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13158 if(not $BName2 or isAnon($BName2)) {
13159 next;
13160 }
13161 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013162 $ChangedTypedef{$Typedef} = 1;
13163 }
13164 }
13165}
13166
13167sub get_symbol_suffix($$)
13168{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013169 my ($Symbol, $Full) = @_;
13170 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013171 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013173 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174 if(not $Full) {
13175 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13176 }
13177 return $Suffix;
13178}
13179
13180sub get_symbol_prefix($$)
13181{
13182 my ($Symbol, $LibVersion) = @_;
13183 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13184 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13185 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013186 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 }
13188 return $ShortName;
13189}
13190
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013191sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013192{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013193 my $Symbol = $_[0];
13194 my $PSymbol = $Symbol;
13195 if(not defined $CompleteSignature{2}{$PSymbol}
13196 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13197 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13198 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013199 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013201 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013202 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013203 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13204 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013205 {
13206 if(defined $CompleteSignature{2}{$PSymbol}
13207 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13208 {
13209 $SourceAlternative{$Symbol} = $PSymbol;
13210 $SourceAlternative_B{$PSymbol} = $Symbol;
13211 if(not defined $CompleteSignature{1}{$PSymbol}
13212 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13213 $SourceReplacement{$Symbol} = $PSymbol;
13214 }
13215 }
13216 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013217 }
13218 else
13219 {
13220 foreach my $Sp ("KV", "VK", "K", "V")
13221 {
13222 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13223 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13224 {
13225 if(defined $CompleteSignature{2}{$PSymbol}
13226 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13227 {
13228 $SourceAlternative{$Symbol} = $PSymbol;
13229 $SourceAlternative_B{$PSymbol} = $Symbol;
13230 if(not defined $CompleteSignature{1}{$PSymbol}
13231 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13232 $SourceReplacement{$Symbol} = $PSymbol;
13233 }
13234 }
13235 }
13236 $PSymbol = $Symbol;
13237 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013238 }
13239 }
13240 }
13241 return "";
13242}
13243
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013244sub getSymKind($$)
13245{
13246 my ($Symbol, $LibVersion) = @_;
13247 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13248 {
13249 return "Global_Data";
13250 }
13251 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13252 {
13253 return "Method";
13254 }
13255 return "Function";
13256}
13257
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013258sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013259{
13260 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013261 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013262
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013263 mergeBases($Level);
13264
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013265 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013266 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013267 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013268 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013269 next;
13270 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013271 if(defined $CompleteSignature{1}{$Symbol}
13272 and $CompleteSignature{1}{$Symbol}{"Header"})
13273 { # double-check added symbol
13274 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013275 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013276 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013277 next;
13278 }
13279 if($Symbol=~/\A(_Z|\?)/)
13280 { # C++
13281 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13282 }
13283 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13284 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013285 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13286 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013287 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013288 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013289 {
13290 if($TName_Tid{1}{$AffectedClass_Name})
13291 { # class should exist in previous version
13292 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13293 { # old v-table is NOT copied by old applications
13294 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13295 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013296 "Target"=>get_Signature($Symbol, 2),
13297 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013298 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013301 }
13302 }
13303 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13305 { # check all removed exported symbols
13306 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 next;
13308 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013309 if(defined $CompleteSignature{2}{$Symbol}
13310 and $CompleteSignature{2}{$Symbol}{"Header"})
13311 { # double-check removed symbol
13312 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013313 }
13314 if($CompleteSignature{1}{$Symbol}{"Private"})
13315 { # skip private methods
13316 next;
13317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013318 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 next;
13320 }
13321 $CheckedSymbols{$Level}{$Symbol} = 1;
13322 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13323 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013324 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13325 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013327 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13328 {
13329 if($TName_Tid{2}{$AffectedClass_Name})
13330 { # class should exist in newer version
13331 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13332 { # old v-table is NOT copied by old applications
13333 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13334 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013335 "Target"=>get_Signature($OverriddenMethod, 1),
13336 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013337 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 }
13341 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013343 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013345 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013346 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013347 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013348 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013351 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 {
13353 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13354 "Target"=>$tr_name{$Symbol},
13355 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013356 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013357 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 else
13359 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013360 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 "Target"=>$tr_name{$Symbol},
13362 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 }
13365 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013366 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013367 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013368 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 {
13370 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13371 "Target"=>$tr_name{$Symbol},
13372 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 else
13376 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013377 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 "Target"=>$tr_name{$Symbol},
13379 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 }
13382 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013383 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13384 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13385 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13386 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13387 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013388 {
13389 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013390 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 $ProblemType = "Global_Data_Symbol_Changed_Type";
13392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013393 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13394 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013395 "Old_Type"=>$RTName1,
13396 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013398 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013399 }
13400 }
13401 }
13402 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013403 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013404 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013406 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013407 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013409 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13411 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013412 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013413 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013414 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013415 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013416 }
13417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013418 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13419 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013420 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013421 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013422 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013423 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 }
13425 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013426 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013427 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013428 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013429 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013431 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013432 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013433 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013435 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013436 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013437 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013438 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013440 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013441 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013442 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013443 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013444 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013445 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013446 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013447 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013448 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013449 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013450 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013451 { # "volatile" to non-"volatile"
13452
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013453 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013454 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013455 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013456 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013457 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013458 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013459 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013460 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013462 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013463 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013464 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013465 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013466 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013468 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013469 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013470 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13471 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013472 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013473 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013474 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013475 }
13476 }
13477 }
13478 }
13479 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013480 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13481 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013482 $CurrentSymbol = $Symbol;
13483
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013484 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13485 if($Level eq "Source")
13486 { # remove symbol version
13487 $Symbol=$SN;
13488 }
13489 else
13490 { # Binary
13491 if(not $SV)
13492 { # symbol without version
13493 if(my $VSym = $SymVer{1}{$Symbol})
13494 { # the symbol is linked with versioned symbol
13495 if($CompleteSignature{2}{$VSym}{"MnglName"})
13496 { # show report for symbol@ver only
13497 next;
13498 }
13499 elsif(not link_symbol($VSym, 2, "-Deps"))
13500 { # changed version: sym@v1 to sym@v2
13501 # do NOT show report for symbol
13502 next;
13503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013504 }
13505 }
13506 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013507 my $PSymbol = $Symbol;
13508 if($Level eq "Source"
13509 and my $S = $SourceReplacement{$Symbol})
13510 { # take a source-compatible replacement function
13511 $PSymbol = $S;
13512 }
13513 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013514 { # private symbols
13515 next;
13516 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013517 if(not defined $CompleteSignature{1}{$Symbol}
13518 or not defined $CompleteSignature{2}{$PSymbol})
13519 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 next;
13521 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013522 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13523 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13524 { # no mangled name
13525 next;
13526 }
13527 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13528 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013529 { # without a header
13530 next;
13531 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013532
13533 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13534 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13535 { # became pure
13536 next;
13537 }
13538 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13539 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13540 { # became non-pure
13541 next;
13542 }
13543
13544 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13545 { # exported, target, inline virtual and pure virtual
13546 next;
13547 }
13548 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13549 { # exported, target, inline virtual and pure virtual
13550 next;
13551 }
13552
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013553 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013554 {
13555 if($CompleteSignature{1}{$Symbol}{"Data"}
13556 and $CompleteSignature{2}{$PSymbol}{"Data"})
13557 {
13558 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13559 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13560 if(defined $Value1)
13561 {
13562 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13563 if(defined $Value2)
13564 {
13565 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13566 if($Value1 ne $Value2)
13567 {
13568 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13569 "Old_Value"=>$Value1,
13570 "New_Value"=>$Value2,
13571 "Target"=>get_Signature($Symbol, 1) );
13572 }
13573 }
13574 }
13575 }
13576 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013577
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013578 if($CompleteSignature{2}{$PSymbol}{"Private"})
13579 {
13580 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13581 "Target"=>get_Signature_M($PSymbol, 2) );
13582 }
13583 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13584 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13585 {
13586 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13587 "Target"=>get_Signature_M($PSymbol, 2) );
13588 }
13589 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13590 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13591 {
13592 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13593 "Target"=>get_Signature_M($PSymbol, 2) );
13594 }
13595
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013597 mergeVirtualTables($Symbol, $Level);
13598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013599 if($COMPILE_ERRORS)
13600 { # if some errors occurred at the compiling stage
13601 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013603 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 { # missed information about parameters in newer version
13605 next;
13606 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013607 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013608 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013609 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013610 next;
13611 }
13612 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013613 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013615 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013616 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13617 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013618 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13619 "Target"=>get_Signature($Symbol, 1)
13620 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013622 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013623 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13624 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013625 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013626 "Target"=>get_Signature($Symbol, 1)
13627 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013629 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13630 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013631 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013632 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013633 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013634 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13635 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13636 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013637 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013638 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013639 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13640 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013641 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013642 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013643 my $ProblemType = "Virtual_Method_Position";
13644 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13645 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013647 if(isUsedClass($Class_Id, 1, $Level))
13648 {
13649 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013650 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013651 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013652 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13653 next;
13654 }
13655 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013656 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13658 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013659 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013661 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 }
13664 }
13665 }
13666 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013667 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13668 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013669 { # do NOT check type changes in pure virtuals
13670 next;
13671 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013672 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013673 if($Symbol=~/\A(_Z|\?)/
13674 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013675 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013676 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013677 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013678 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013679 }
13680 }
13681 else
13682 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013683 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013685 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013686 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13687 last if($PType2_Name eq "...");
13688 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13689 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013690 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013691 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013692 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013693 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13694 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13696 $ParamPos_Prev = "lost";
13697 }
13698 }
13699 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013700 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013701 }
13702 if($ParamPos_Prev eq "lost")
13703 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013704 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013705 {
13706 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013707 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013708 $ProblemType = "Added_Unnamed_Parameter";
13709 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013710 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013711 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013712 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013713 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013714 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013715 }
13716 else
13717 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013718 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013719 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013720 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13722 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013723 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013724 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013725 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013726 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013727 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013728 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013729 "Param_Type"=>$PType2_Name,
13730 "Old_Value"=>$PName_Old,
13731 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013732 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013733 }
13734 }
13735 else
13736 {
13737 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013738 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013739 $ProblemType = "Added_Middle_Unnamed_Parameter";
13740 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013741 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013742 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013743 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013744 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013745 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013746 }
13747 }
13748 }
13749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013750 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013751 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013752 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013753 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013754 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013755 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013756 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013757 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013758 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013759 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13760 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013761 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013762 }
13763 }
13764 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013765 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013766 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013767 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013768 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13769 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013770 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13771 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013773 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013774 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013775 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13776 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013777 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13778 $ParamPos_New = "lost";
13779 }
13780 }
13781 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013782 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013783 }
13784 if($ParamPos_New eq "lost")
13785 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013786 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013787 {
13788 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013789 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 $ProblemType = "Removed_Unnamed_Parameter";
13791 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013792 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013793 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013794 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013795 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013796 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013798 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013800 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013801 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013802 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013803 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013804 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013805 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013806 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013807 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013808 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013809 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013810 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013811 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013812 "Old_Value"=>$PName,
13813 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013814 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013815 }
13816 }
13817 else
13818 {
13819 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013820 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013821 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13822 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013823 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013824 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013825 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013826 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013827 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013828 }
13829 }
13830 }
13831 }
13832 }
13833 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013834 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13835 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013836 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013837
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013838 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013840 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13841 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013842 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013843
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013844 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013845 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 if($SubProblemType eq "Return_Type_And_Size") {
13847 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13848 }
13849 elsif($SubProblemType eq "Return_Type_Format") {
13850 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13851 }
13852 else {
13853 $ProblemTypes{"Global_Data_Type"} = 1;
13854 }
13855
13856 # quals
13857 if($SubProblemType eq "Return_Type"
13858 or $SubProblemType eq "Return_Type_And_Size"
13859 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013860 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13862 { # const to non-const
13863 if($RR==2) {
13864 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13865 }
13866 else {
13867 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13868 }
13869 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013871 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13872 { # non-const to const
13873 if($RA==2) {
13874 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13875 }
13876 else {
13877 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13878 }
13879 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013880 }
13881 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013882 }
13883 else
13884 {
13885 # quals
13886 if($SubProblemType eq "Return_Type"
13887 or $SubProblemType eq "Return_Type_And_Size"
13888 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013889 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013890 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013891 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 if(addedQual($Old_Value, $New_Value, "volatile"))
13893 {
13894 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13895 if($Level ne "Source"
13896 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13897 $ProblemTypes{"Return_Type"} = 1;
13898 }
13899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013900 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013901 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13902 {
13903 if($RA==2) {
13904 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13905 }
13906 else {
13907 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13908 }
13909 if($Level ne "Source"
13910 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13911 $ProblemTypes{"Return_Type"} = 1;
13912 }
13913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013914 }
13915 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013916 if($Level eq "Binary"
13917 and not $CompleteSignature{1}{$Symbol}{"Data"})
13918 {
13919 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13920 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13921 { # if one of the architectures is unknown
13922 # then set other arhitecture to unknown too
13923 ($Arch1, $Arch2) = ("unknown", "unknown");
13924 }
13925 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013926 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013927 {
13928 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13929 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13930 }
13931 else
13932 {
13933 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13934 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13935 }
13936
13937 if($SubProblemType eq "Return_Type_Became_Void")
13938 {
13939 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13940 { # parameters stack has been affected
13941 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013942 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013943 }
13944 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013945 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013946 }
13947 }
13948 }
13949 elsif($SubProblemType eq "Return_Type_From_Void")
13950 {
13951 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13952 { # parameters stack has been affected
13953 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013954 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013955 }
13956 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013957 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013958 }
13959 }
13960 }
13961 elsif($SubProblemType eq "Return_Type"
13962 or $SubProblemType eq "Return_Type_And_Size"
13963 or $SubProblemType eq "Return_Type_Format")
13964 {
13965 if($Conv1{"Method"} ne $Conv2{"Method"})
13966 {
13967 if($Conv1{"Method"} eq "stack")
13968 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013969 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013970 }
13971 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013972 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013973 }
13974 }
13975 else
13976 {
13977 if($Conv1{"Method"} eq "reg")
13978 {
13979 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13980 {
13981 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013982 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013983 }
13984 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013985 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013986 }
13987 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013988 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013989 }
13990 }
13991 }
13992 }
13993 }
13994 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013995
13996 if(not keys(%ProblemTypes))
13997 { # default
13998 $ProblemTypes{$SubProblemType} = 1;
13999 }
14000
14001 foreach my $ProblemType (keys(%ProblemTypes))
14002 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014003 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014005 }
14006 if($ReturnType1_Id and $ReturnType2_Id)
14007 {
14008 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014009 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
14010
14011 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014012
14013 if($CompleteSignature{1}{$Symbol}{"Data"})
14014 {
14015 if($Level eq "Binary")
14016 {
14017 if(get_PLevel($ReturnType1_Id, 1)==0)
14018 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014019 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014020 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014021
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014022 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14023 {
14024 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014025 {
14026 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14027 {
14028 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14029 last;
14030 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014031 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014032 }
14033 }
14034 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014035 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014036 {
14037 if(defined $GlobalDataObject{1}{$Symbol}
14038 and defined $GlobalDataObject{2}{$Symbol})
14039 {
14040 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14041 my $New_Size = $GlobalDataObject{2}{$Symbol};
14042 if($Old_Size!=$New_Size)
14043 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014044 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014045 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014046 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014047 }
14048 }
14049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014050 }
14051 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014052
14053 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014054 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014055 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014057 my $NewLocation = "retval";
14058 if($SubLocation and $SubLocation ne "retval") {
14059 $NewLocation = "retval->".$SubLocation;
14060 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014061 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14062 }
14063 }
14064
14065 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14066 {
14067 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14068 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014069 my $NewLocation = "retval";
14070 if($SubLocation and $SubLocation ne "retval") {
14071 $NewLocation = "retval->".$SubLocation;
14072 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014073 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014074 }
14075 }
14076 }
14077
14078 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014079 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14080 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14081 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014082 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014084 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14085 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014086 if($ThisPtr1_Id and $ThisPtr2_Id)
14087 {
14088 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014089 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14090 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014091 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014092 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014093 {
14094 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014095 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014096 }
14097 }
14098 }
14099 }
14100 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014101 if($Level eq "Binary") {
14102 mergeVTables($Level);
14103 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014104 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14105 $CheckedSymbols{$Level}{$Symbol} = 1;
14106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014107}
14108
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014109sub rmQuals($$)
14110{
14111 my ($Value, $Qual) = @_;
14112 if(not $Qual) {
14113 return $Value;
14114 }
14115 if($Qual eq "all")
14116 { # all quals
14117 $Qual = "const|volatile|restrict";
14118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014119 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014120 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014121 }
14122 return $Value;
14123}
14124
14125sub cmpBTypes($$$$)
14126{
14127 my ($T1, $T2, $V1, $V2) = @_;
14128 $T1 = uncover_typedefs($T1, $V1);
14129 $T2 = uncover_typedefs($T2, $V2);
14130 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14131}
14132
14133sub addedQual($$$)
14134{
14135 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014136 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014137}
14138
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014139sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014140{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014141 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014142 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143}
14144
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014145sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014146{
14147 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14148 $Old_Value = uncover_typedefs($Old_Value, $V1);
14149 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014150
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014151 if($Old_Value eq $New_Value)
14152 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014153 return 0;
14154 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014155 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014156 { # without a qual
14157 return 0;
14158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014159 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160 { # became non-qual
14161 return 1;
14162 }
14163 else
14164 {
14165 my @BQ1 = getQualModel($Old_Value, $Qual);
14166 my @BQ2 = getQualModel($New_Value, $Qual);
14167 foreach (0 .. $#BQ1)
14168 { # removed qual
14169 if($BQ1[$_]==1
14170 and $BQ2[$_]!=1)
14171 {
14172 return 2;
14173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014174 }
14175 }
14176 return 0;
14177}
14178
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014179sub getQualModel($$)
14180{
14181 my ($Value, $Qual) = @_;
14182 if(not $Qual) {
14183 return $Value;
14184 }
14185
14186 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014187 while($Value=~/(\w+)/)
14188 {
14189 my $W = $1;
14190
14191 if($W eq $Qual) {
14192 $Value=~s/\b$W\b/\@/g;
14193 }
14194 else {
14195 $Value=~s/\b$W\b//g;
14196 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014197 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014198
14199 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014200 $Value=~s/[^\*\&\w]+//g;
14201
14202 # modeling
14203 # int*const*const == 011
14204 # int**const == 001
14205 my @Model = ();
14206 my @Elems = split(/[\*\&]/, $Value);
14207 if(not @Elems) {
14208 return (0);
14209 }
14210 foreach (@Elems)
14211 {
14212 if($_ eq $Qual) {
14213 push(@Model, 1);
14214 }
14215 else {
14216 push(@Model, 0);
14217 }
14218 }
14219
14220 return @Model;
14221}
14222
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014223my %StringTypes = map {$_=>1} (
14224 "char*",
14225 "char const*"
14226);
14227
14228my %CharTypes = map {$_=>1} (
14229 "char",
14230 "char const"
14231);
14232
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014233sub showVal($$$)
14234{
14235 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014236 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014237 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014238 if(substr($Value, 0, 2) eq "_Z")
14239 {
14240 if(my $Unmangled = $tr_name{$Value}) {
14241 return $Unmangled;
14242 }
14243 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014244 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014245 { # strings
14246 return "\"$Value\"";
14247 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014248 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014249 { # characters
14250 return "\'$Value\'";
14251 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014252 if($Value eq "")
14253 { # other
14254 return "\'\'";
14255 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014256 return $Value;
14257}
14258
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014259sub getRegs($$$)
14260{
14261 my ($LibVersion, $Symbol, $Pos) = @_;
14262
14263 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14264 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014265 my %Regs = ();
14266 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14267 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014268 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014269 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14270 }
14271 }
14272
14273 return join(", ", sort keys(%Regs));
14274 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014275 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14276 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14277 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14278 {
14279 return "unknown";
14280 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014281
14282 return undef;
14283}
14284
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014285sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014286{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014287 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014288 if(not $Symbol) {
14289 return;
14290 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014291 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14292 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14293 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14294 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014295 if(not $PType1_Id
14296 or not $PType2_Id) {
14297 return;
14298 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014299
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014300 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014301 { # do not merge "this"
14302 if($PName1 eq "this" or $PName2 eq "this") {
14303 return;
14304 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014305 }
14306
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014307 my %Type1 = get_Type($PType1_Id, 1);
14308 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014309
14310 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14311
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014312 my %BaseType1 = get_BaseType($PType1_Id, 1);
14313 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014314
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014315 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014316
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014317 if($Level eq "Binary")
14318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014319 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014320 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14321 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14322 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14323 {
14324 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014325 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014326 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014327 }
14328 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14329 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14330 {
14331 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014332 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014333 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014335 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014336
14337 if(defined $UsedDump{1}{"DWARF"}
14338 and defined $UsedDump{2}{"DWARF"})
14339 {
14340 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14341 {
14342 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14343 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014344
14345 if($Old_Regs ne "unknown"
14346 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014347 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014348 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014349 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014350 if($Old_Regs ne $New_Regs)
14351 {
14352 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14353 "Target"=>$PName1,
14354 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14355 "Old_Value"=>$Old_Regs,
14356 "New_Value"=>$New_Regs );
14357 }
14358 }
14359 elsif($Old_Regs and not $New_Regs)
14360 {
14361 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014362 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014363 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014364 "Old_Value"=>$Old_Regs );
14365 }
14366 elsif(not $Old_Regs and $New_Regs)
14367 {
14368 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14369 "Target"=>$PName1,
14370 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014371 "New_Value"=>$New_Regs );
14372 }
14373 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014374
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014375 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14376 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14377 {
14378 if($Old_Offset ne $New_Offset)
14379 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014380 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14381 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14382
14383 $Old_Offset = $Old_Offset - $Start1;
14384 $New_Offset = $New_Offset - $Start2;
14385
14386 if($Old_Offset ne $New_Offset)
14387 {
14388 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14389 "Target"=>$PName1,
14390 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14391 "Old_Value"=>$Old_Offset,
14392 "New_Value"=>$New_Offset );
14393 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014394 }
14395 }
14396 }
14397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014398 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014399 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14400 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014401 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014402 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014403 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14404 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014405 if(not checkDump(1, "2.13")
14406 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014407 { # support for old ABI dumps
14408 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014409 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014410 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014411 and $Value_Old eq "false" and $Value_New eq "0")
14412 { # int class::method ( bool p = 0 );
14413 # old ABI dumps: "false"
14414 # new ABI dumps: "0"
14415 $Value_Old = "0";
14416 }
14417 }
14418 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014419 if(not checkDump(1, "2.18")
14420 and checkDump(2, "2.18"))
14421 { # support for old ABI dumps
14422 if(not defined $Value_Old
14423 and substr($Value_New, 0, 2) eq "_Z") {
14424 $Value_Old = $Value_New;
14425 }
14426 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014427 if(defined $Value_Old)
14428 {
14429 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14430 if(defined $Value_New)
14431 {
14432 $Value_New = showVal($Value_New, $PType2_Id, 2);
14433 if($Value_Old ne $Value_New)
14434 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014435 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014436 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014437 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014438 "Old_Value"=>$Value_Old,
14439 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014440 }
14441 }
14442 else
14443 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014444 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014445 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014446 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014447 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014448 }
14449 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014450 elsif(defined $Value_New)
14451 {
14452 $Value_New = showVal($Value_New, $PType2_Id, 2);
14453 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14454 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014455 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014456 "New_Value"=>$Value_New );
14457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014458 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014459
14460 if($ChkRnmd)
14461 {
14462 if($PName1 and $PName2 and $PName1 ne $PName2
14463 and $PType1_Id!=-1 and $PType2_Id!=-1
14464 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14465 { # except unnamed "..." value list (Id=-1)
14466 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14467 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014468 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014469 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14470 "Old_Value"=>$PName1,
14471 "New_Value"=>$PName2,
14472 "New_Signature"=>get_Signature($Symbol, 2) );
14473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014474 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014477 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014478
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 foreach my $SubProblemType (keys(%SubProblems))
14480 { # add new problems, remove false alarms
14481 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14482 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014483
14484 # quals
14485 if($SubProblemType eq "Parameter_Type"
14486 or $SubProblemType eq "Parameter_Type_And_Size"
14487 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014488 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014489 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014490 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014491 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014492 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014493 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014494 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14495 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14496 }
14497 }
14498 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14499 {
14500 if(removedQual($Old_Value, $New_Value, "volatile")) {
14501 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014502 }
14503 }
14504 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14505 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14506 { # int to "int const"
14507 delete($SubProblems{$SubProblemType});
14508 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014509 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14511 { # "int const" to int
14512 delete($SubProblems{$SubProblemType});
14513 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014514 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14515 { # "const" to non-"const"
14516 if($RR==2) {
14517 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14518 }
14519 else {
14520 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14521 }
14522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014523 }
14524 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014525
14526 if($Level eq "Source")
14527 {
14528 foreach my $SubProblemType (keys(%SubProblems))
14529 {
14530 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14531 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14532
14533 if($SubProblemType eq "Parameter_Type")
14534 {
14535 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14536 delete($SubProblems{$SubProblemType});
14537 }
14538 }
14539 }
14540 }
14541
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014542 foreach my $SubProblemType (keys(%SubProblems))
14543 { # modify/register problems
14544 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14545 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014546 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14547 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014548
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014549 my $NewProblemType = $SubProblemType;
14550 if($Old_Value eq "..." and $New_Value ne "...")
14551 { # change from "..." to "int"
14552 if($ParamPos1==0)
14553 { # ISO C requires a named argument before "..."
14554 next;
14555 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014556 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014557 }
14558 elsif($New_Value eq "..." and $Old_Value ne "...")
14559 { # change from "int" to "..."
14560 if($ParamPos2==0)
14561 { # ISO C requires a named argument before "..."
14562 next;
14563 }
14564 $NewProblemType = "Parameter_Became_VaList";
14565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014566 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014567 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014568 {
14569 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014570 if($Arch1 eq "unknown"
14571 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014572 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014573 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 ($Arch1, $Arch2) = ("unknown", "unknown");
14575 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014576 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014577 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014578 { # real
14579 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14580 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14581 }
14582 else
14583 { # model
14584 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14585 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14586 }
14587 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014589 if($Conv1{"Method"} eq "stack")
14590 {
14591 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14592 $NewProblemType = "Parameter_Type_And_Stack";
14593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014594 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014595 elsif($Conv1{"Method"} eq "reg")
14596 {
14597 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14598 $NewProblemType = "Parameter_Type_And_Register";
14599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600 }
14601 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014602 elsif($Conv1{"Method"} ne "unknown"
14603 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014604 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014605 if($Conv1{"Method"} eq "stack") {
14606 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014607 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014608 elsif($Conv1{"Method"} eq "register") {
14609 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014610 }
14611 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014612 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14613 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014615 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014616 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014617 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014618 "New_Signature"=>get_Signature($Symbol, 2) );
14619 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014620 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014622 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014623
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014624 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014625 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14626 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014628 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014629 {
14630 my $NewProblemType = $SubProblemType;
14631 if($SubProblemType eq "DataType_Size")
14632 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014633 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014634 { # stack has been affected
14635 $NewProblemType = "DataType_Size_And_Stack";
14636 }
14637 }
14638 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014639 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014640 }
14641 }
14642}
14643
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014644sub find_ParamPair_Pos_byName($$$)
14645{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014646 my ($Name, $Symbol, $LibVersion) = @_;
14647 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014648 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014649 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14650 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014651 {
14652 return $ParamPos;
14653 }
14654 }
14655 return "lost";
14656}
14657
14658sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14659{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014660 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014661 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014662 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014663 {
14664 next if($Order eq "backward" and $ParamPos>$MediumPos);
14665 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014666 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14667 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014668 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669 push(@Positions, $ParamPos);
14670 }
14671 }
14672 return @Positions;
14673}
14674
14675sub getTypeIdByName($$)
14676{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014677 my ($TypeName, $LibVersion) = @_;
14678 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679}
14680
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014681sub diffTypes($$$)
14682{
14683 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14684 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14685 }
14686 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14687 { # skip recursive declarations
14688 return 0;
14689 }
14690
14691 pushType($_[0], $_[1], \@RecurTypes_Diff);
14692 my $Diff = diffTypes_I(@_);
14693 pop(@RecurTypes_Diff);
14694
14695 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14696}
14697
14698sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014699{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014700 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014701
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014702 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14703 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014704
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014705 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14706 { # equal types
14707 return 0;
14708 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014709 if($Type1_Pure{"Name"} eq "void")
14710 { # from void* to something
14711 return 0;
14712 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014713 if($Type2_Pure{"Name"} eq "void")
14714 { # from something to void*
14715 return 0;
14716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014717 if($Type1_Pure{"Name"}=~/\*/
14718 or $Type2_Pure{"Name"}=~/\*/)
14719 { # compared in detectTypeChange()
14720 return 0;
14721 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014722
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014723 my %FloatType = map {$_=>1} (
14724 "float",
14725 "double",
14726 "long double"
14727 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014728
14729 my $T1 = $Type1_Pure{"Type"};
14730 my $T2 = $Type2_Pure{"Type"};
14731
14732 if($T1 eq "Struct"
14733 and $T2 eq "Class")
14734 { # compare as data structures
14735 $T2 = "Struct";
14736 }
14737
14738 if($T1 eq "Class"
14739 and $T2 eq "Struct")
14740 { # compare as data structures
14741 $T1 = "Struct";
14742 }
14743
14744 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014746 if($T1 eq "Intrinsic"
14747 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014748 { # "int" to "enum"
14749 return 0;
14750 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014751 elsif($T2 eq "Intrinsic"
14752 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014753 { # "enum" to "int"
14754 return 0;
14755 }
14756 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014757 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758 # ...
14759 return 1;
14760 }
14761 }
14762 else
14763 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014764 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014765 {
14766 if($FloatType{$Type1_Pure{"Name"}}
14767 or $FloatType{$Type2_Pure{"Name"}})
14768 { # "float" to "double"
14769 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014770 if($Level eq "Source")
14771 { # Safe
14772 return 0;
14773 }
14774 else {
14775 return 1;
14776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014777 }
14778 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014779 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014780 {
14781 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14782 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014783 if(not @Membs1
14784 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014785 { # private
14786 return 0;
14787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014788 if($#Membs1!=$#Membs2)
14789 { # different number of elements
14790 return 1;
14791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014792 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014793 {
14794 foreach my $Pos (@Membs1)
14795 { # compare elements by name and value
14796 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14797 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14798 { # different names
14799 return 1;
14800 }
14801 }
14802 }
14803 else
14804 {
14805 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014806 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014807 if($Level eq "Source")
14808 {
14809 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14810 { # different names
14811 return 1;
14812 }
14813 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014814
14815 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14816 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14817
14818 if($MT1{"Name"} ne $MT2{"Name"}
14819 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14820 {
14821 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14822 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14823
14824 if($PL1 ne $PL2)
14825 { # different pointer level
14826 return 1;
14827 }
14828
14829 # compare base types
14830 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14831 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14832
14833 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14834 { # different types
14835 return 1;
14836 }
14837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014838 }
14839 }
14840 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014841 else
14842 {
14843 # TODO: arrays, etc.
14844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014845 }
14846 return 0;
14847}
14848
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014849sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014850{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014851 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014852 if(not $Type1_Id or not $Type2_Id) {
14853 return ();
14854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014855 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014856 my %Type1 = get_Type($Type1_Id, 1);
14857 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014858 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14859 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014860
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014861 if(defined $SkipTypedefUncover)
14862 {
14863 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14864 return ();
14865 }
14866
14867 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14868 return ();
14869 }
14870 }
14871
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014872 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14873 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 +040014874
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014875 if(defined $UsedDump{1}{"DWARF"})
14876 {
14877 if($Type1_Pure{"Name"} eq "__unknown__"
14878 or $Type2_Pure{"Name"} eq "__unknown__"
14879 or $Type1_Base{"Name"} eq "__unknown__"
14880 or $Type2_Base{"Name"} eq "__unknown__")
14881 { # Error ABI dump
14882 return ();
14883 }
14884 }
14885
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014886 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14887 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014888 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14889 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14890 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14891 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14892 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14893 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14894 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014895 if($Type1{"Name"} eq $Type2{"Name"})
14896 {
14897 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14898 { # will be reported in mergeTypes() as typedef problem
14899 return ();
14900 }
14901 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14902 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14903 if(%Typedef_1 and %Typedef_2)
14904 {
14905 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14906 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14907 { # const Typedef
14908 return ();
14909 }
14910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014911 }
14912 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14913 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014914 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014915 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14916 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014917 {
14918 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14919 "Old_Value"=>$Type1_Base{"Name"},
14920 "New_Value"=>$Type2_Base{"Name"},
14921 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014922 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014923 }
14924 else
14925 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014926 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 { # format change
14928 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14929 "Old_Value"=>$Type1_Base{"Name"},
14930 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014931 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014932 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014933 }
14934 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14935 {
14936 %{$LocalProblems{$Prefix."_BaseType"}}=(
14937 "Old_Value"=>$Type1_Base{"Name"},
14938 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014939 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014940 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014941 }
14942 }
14943 }
14944 }
14945 elsif($Type1{"Name"} ne $Type2{"Name"})
14946 { # type change
14947 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14948 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014949 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014950 and $Type1_Pure{"Name"} eq "void")
14951 {
14952 %{$LocalProblems{"Return_Type_From_Void"}}=(
14953 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014954 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014956 elsif($Prefix eq "Return"
14957 and $Type2_Pure{"Name"} eq "void")
14958 {
14959 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14960 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014961 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014963 else
14964 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014965 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014966 and $Type1{"Size"} and $Type2{"Size"}
14967 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014968 {
14969 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14970 "Old_Value"=>$Type1{"Name"},
14971 "New_Value"=>$Type2{"Name"},
14972 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014973 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014974 }
14975 else
14976 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014977 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014978 { # format change
14979 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14980 "Old_Value"=>$Type1{"Name"},
14981 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014982 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014983 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 }
14985 elsif(tNameLock($Type1_Id, $Type2_Id))
14986 { # FIXME: correct this condition
14987 %{$LocalProblems{$Prefix."_Type"}}=(
14988 "Old_Value"=>$Type1{"Name"},
14989 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014990 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014991 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 }
14993 }
14994 }
14995 }
14996 }
14997 if($Type1_PLevel!=$Type2_PLevel)
14998 {
14999 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
15000 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
15001 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015002 if($Level eq "Source")
15003 {
15004 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 "Old_Value"=>$Type1_PLevel,
15006 "New_Value"=>$Type2_PLevel);
15007 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015008 else
15009 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015010 if($Type2_PLevel>$Type1_PLevel)
15011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015012 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
15013 "Old_Value"=>$Type1_PLevel,
15014 "New_Value"=>$Type2_PLevel);
15015 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015016 else
15017 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015018 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
15019 "Old_Value"=>$Type1_PLevel,
15020 "New_Value"=>$Type2_PLevel);
15021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 }
15023 }
15024 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040015025 if($Type1_Pure{"Type"} eq "Array"
15026 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 { # base_type[N] -> base_type[N]
15028 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015029 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015030 foreach my $SubProblemType (keys(%SubProblems))
15031 {
15032 $SubProblemType=~s/_Type/_BaseType/g;
15033 next if(defined $LocalProblems{$SubProblemType});
15034 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
15035 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
15036 }
15037 }
15038 }
15039 return %LocalProblems;
15040}
15041
15042sub tNameLock($$)
15043{
15044 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015045 my $Changed = 0;
15046 if(differentDumps("G"))
15047 { # different GCC versions
15048 $Changed = 1;
15049 }
15050 elsif(differentDumps("V"))
15051 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015052 if(not checkDump(1, "2.20")
15053 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015054 { # latest names update
15055 # 2.6: added restrict qualifier
15056 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015057 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015058 $Changed = 1;
15059 }
15060 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015061
15062 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15063 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15064
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015065 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15066 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15067
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015068 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015069 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015070 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015071 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015072 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015073 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015074 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015075 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015076 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015077 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015078 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15079 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15080 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015081 { # equal base types
15082 return 0;
15083 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015085 if(not checkDump(1, "2.13")
15086 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015087 { # broken array names in ABI dumps < 2.13
15088 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015089 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090 return 0;
15091 }
15092 }
15093
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015094 if(not checkDump(1, "2.6")
15095 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015096 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015097 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015098 and $TN2=~/\brestrict\b/) {
15099 return 0;
15100 }
15101 }
15102
15103 if(not checkDump(1, "2.20")
15104 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015105 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015106 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15107 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015108 return 0;
15109 }
15110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015112 else
15113 {
15114 # typedef struct {...} type_t
15115 # typedef struct type_t {...} type_t
15116 if(index($TN1, " ".$TN2)!=-1)
15117 {
15118 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15119 return 0;
15120 }
15121 }
15122 if(index($TN2, " ".$TN1)!=-1)
15123 {
15124 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15125 return 0;
15126 }
15127 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015128
15129 if($TT1 eq "FuncPtr"
15130 and $TT2 eq "FuncPtr")
15131 {
15132 my $TN1_C = $TN1;
15133 my $TN2_C = $TN2;
15134
15135 $TN1_C=~s/\b(struct|union) //g;
15136 $TN2_C=~s/\b(struct|union) //g;
15137
15138 if($TN1_C eq $TN2_C) {
15139 return 0;
15140 }
15141 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015142 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015143
15144 my ($N1, $N2) = ($TN1, $TN2);
15145 $N1=~s/\b(struct|union) //g;
15146 $N2=~s/\b(struct|union) //g;
15147
15148 if($N1 eq $N2)
15149 { # QList<struct QUrl> and QList<QUrl>
15150 return 0;
15151 }
15152
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015153 return 1;
15154}
15155
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015156sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015158 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015159 if(defined $Cache{"differentDumps"}{$Check}) {
15160 return $Cache{"differentDumps"}{$Check};
15161 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015162 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015163 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015164 if($Check eq "G")
15165 {
15166 if(getGccVersion(1) ne getGccVersion(2))
15167 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015168 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015170 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015171 if($Check eq "V")
15172 {
15173 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15174 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15175 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015176 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015177 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015179 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015180 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015181}
15182
15183sub formatVersion($$)
15184{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015185 my ($V, $Digits) = @_;
15186 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015187 return join(".", splice(@Elems, 0, $Digits));
15188}
15189
15190sub htmlSpecChars($)
15191{
15192 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015193 if(not $Str) {
15194 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015196 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15197 $Str=~s/</&lt;/g;
15198 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15199 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015200 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15201 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015203 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015204 $Str=~s/\n/<br\/>/g;
15205 $Str=~s/\"/&quot;/g;
15206 $Str=~s/\'/&#39;/g;
15207 return $Str;
15208}
15209
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015210sub xmlSpecChars($)
15211{
15212 my $Str = $_[0];
15213 if(not $Str) {
15214 return $Str;
15215 }
15216
15217 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15218 $Str=~s/</&lt;/g;
15219 $Str=~s/>/&gt;/g;
15220
15221 $Str=~s/\"/&quot;/g;
15222 $Str=~s/\'/&#39;/g;
15223
15224 return $Str;
15225}
15226
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015227sub xmlSpecChars_R($)
15228{
15229 my $Str = $_[0];
15230 if(not $Str) {
15231 return $Str;
15232 }
15233
15234 $Str=~s/&amp;/&/g;
15235 $Str=~s/&lt;/</g;
15236 $Str=~s/&gt;/>/g;
15237
15238 $Str=~s/&quot;/"/g;
15239 $Str=~s/&#39;/'/g;
15240
15241 return $Str;
15242}
15243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015244sub black_name($)
15245{
15246 my $Name = $_[0];
15247 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15248}
15249
15250sub highLight_Signature($)
15251{
15252 my $Signature = $_[0];
15253 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15254}
15255
15256sub highLight_Signature_Italic_Color($)
15257{
15258 my $Signature = $_[0];
15259 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15260}
15261
15262sub separate_symbol($)
15263{
15264 my $Symbol = $_[0];
15265 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15266 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15267 ($Name, $Spec, $Ver) = ($1, $2, $3);
15268 }
15269 return ($Name, $Spec, $Ver);
15270}
15271
15272sub cut_f_attrs($)
15273{
15274 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15275 return $2;
15276 }
15277 return "";
15278}
15279
15280sub highLight_Signature_PPos_Italic($$$$$)
15281{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015282 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15283 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15285 my $Return = "";
15286 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15287 $Return = $2;
15288 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015289 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015291 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015292 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015293 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015294 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015295 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015296 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015297 }
15298 return $Signature;
15299 }
15300 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15301 $Begin.=" " if($Begin!~/ \Z/);
15302 $End = cut_f_attrs($Signature);
15303 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015304 my ($Short, $Params) = split_Signature($Signature);
15305 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015306 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015307 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015308 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015309 $Part=~s/\A\s+|\s+\Z//g;
15310 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15311 if($Part=~/\([\*]+(\w+)\)/i) {
15312 $ParamName = $1;#func-ptr
15313 }
15314 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15315 $ParamName = $1;
15316 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015317 if(not $ParamName)
15318 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015319 push(@Parts, $Part_Styled);
15320 next;
15321 }
15322 if($ItalicParams and not $TName_Tid{1}{$Part}
15323 and not $TName_Tid{2}{$Part})
15324 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015325 my $Style = "<i>$ParamName</i>";
15326
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015327 if($Param_Pos ne ""
15328 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015329 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015330 }
15331 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015332 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015333 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015334
15335 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015336 }
15337 $Part_Styled=~s/,(\w)/, $1/g;
15338 push(@Parts, $Part_Styled);
15339 }
15340 if(@Parts)
15341 {
15342 foreach my $Num (0 .. $#Parts)
15343 {
15344 if($Num==$#Parts)
15345 { # add ")" to the last parameter
15346 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15347 }
15348 elsif(length($Parts[$Num])<=45) {
15349 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15350 }
15351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015352 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353 }
15354 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015355 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015356 }
15357 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015358 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015360 $Signature=~s!\[\]![&#160;]!g;
15361 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015362 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15363 if($SymbolVersion) {
15364 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15365 }
15366 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015367}
15368
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015369sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015370{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015371 my $Signature = $_[0];
15372 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15373 {
15374 $Signature=~s/\A\Q$ShortName\E\(//g;
15375 cut_f_attrs($Signature);
15376 $Signature=~s/\)\Z//;
15377 return ($ShortName, $Signature);
15378 }
15379
15380 # error
15381 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015382}
15383
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015384sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015385{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015386 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015387 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015388 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15389 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015390 foreach my $Pos (0 .. length($Params) - 1)
15391 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015392 my $S = substr($Params, $Pos, 1);
15393 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015394 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015395 }
15396 if($S eq "," and
15397 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015399 if($Comma)
15400 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015401 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015402 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015403 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015404 }
15405 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015406 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015407 }
15408 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015409 if(not $Sp)
15410 { # remove spaces
15411 foreach (@Parts)
15412 {
15413 s/\A //g;
15414 s/ \Z//g;
15415 }
15416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015417 return @Parts;
15418}
15419
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015420sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421{
15422 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015423 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015424 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015425 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15426 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015427 $Center+=length($1);
15428 }
15429 foreach my $Pos (0 .. length($Sign)-1)
15430 {
15431 my $S = substr($Sign, $Pos, 1);
15432 if($S eq $Target)
15433 {
15434 if($B{"("}==$B{")"}
15435 and $B{"<"}==$B{">"}) {
15436 return $Center;
15437 }
15438 }
15439 if(defined $B{$S}) {
15440 $B{$S}+=1;
15441 }
15442 $Center+=1;
15443 }
15444 return 0;
15445}
15446
15447sub appendFile($$)
15448{
15449 my ($Path, $Content) = @_;
15450 return if(not $Path);
15451 if(my $Dir = get_dirname($Path)) {
15452 mkpath($Dir);
15453 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015454 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015455 print FILE $Content;
15456 close(FILE);
15457}
15458
15459sub writeFile($$)
15460{
15461 my ($Path, $Content) = @_;
15462 return if(not $Path);
15463 if(my $Dir = get_dirname($Path)) {
15464 mkpath($Dir);
15465 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015466 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015467 print FILE $Content;
15468 close(FILE);
15469}
15470
15471sub readFile($)
15472{
15473 my $Path = $_[0];
15474 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015475 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476 local $/ = undef;
15477 my $Content = <FILE>;
15478 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015479 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015480 $Content=~s/\r/\n/g;
15481 }
15482 return $Content;
15483}
15484
15485sub get_filename($)
15486{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015487 if(defined $Cache{"get_filename"}{$_[0]}) {
15488 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015489 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015490 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15491 return ($Cache{"get_filename"}{$_[0]}=$1);
15492 }
15493 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015494}
15495
15496sub get_dirname($)
15497{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015498 if(defined $Cache{"get_dirname"}{$_[0]}) {
15499 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015500 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015501 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15502 return ($Cache{"get_dirname"}{$_[0]}=$1);
15503 }
15504 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015505}
15506
15507sub separate_path($) {
15508 return (get_dirname($_[0]), get_filename($_[0]));
15509}
15510
15511sub esc($)
15512{
15513 my $Str = $_[0];
15514 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15515 return $Str;
15516}
15517
15518sub readLineNum($$)
15519{
15520 my ($Path, $Num) = @_;
15521 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015522 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015523 foreach (1 ... $Num) {
15524 <FILE>;
15525 }
15526 my $Line = <FILE>;
15527 close(FILE);
15528 return $Line;
15529}
15530
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015531sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015533 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015534 return () if(not $Path or not -f $Path);
15535 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015536 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15537 {
15538 foreach my $AttrVal (split(/;/, $1))
15539 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540 if($AttrVal=~/(.+):(.+)/)
15541 {
15542 my ($Name, $Value) = ($1, $2);
15543 $Attributes{$Name} = $Value;
15544 }
15545 }
15546 }
15547 return \%Attributes;
15548}
15549
15550sub is_abs($) {
15551 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15552}
15553
15554sub get_abs_path($)
15555{ # abs_path() should NOT be called for absolute inputs
15556 # because it can change them
15557 my $Path = $_[0];
15558 if(not is_abs($Path)) {
15559 $Path = abs_path($Path);
15560 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015561 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015562}
15563
15564sub get_OSgroup()
15565{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015566 my $N = $Config{"osname"};
15567 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015568 return "macos";
15569 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015570 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015571 return "bsd";
15572 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015573 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 return "beos";
15575 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015576 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015577 return "symbian";
15578 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015579 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 return "windows";
15581 }
15582 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015583 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015584 }
15585}
15586
15587sub getGccVersion($)
15588{
15589 my $LibVersion = $_[0];
15590 if($GCC_VERSION{$LibVersion})
15591 { # dump version
15592 return $GCC_VERSION{$LibVersion};
15593 }
15594 elsif($UsedDump{$LibVersion}{"V"})
15595 { # old-version dumps
15596 return "unknown";
15597 }
15598 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15599 if(not $GccVersion) {
15600 return "unknown";
15601 }
15602 return $GccVersion;
15603}
15604
15605sub showArch($)
15606{
15607 my $Arch = $_[0];
15608 if($Arch eq "arm"
15609 or $Arch eq "mips") {
15610 return uc($Arch);
15611 }
15612 return $Arch;
15613}
15614
15615sub getArch($)
15616{
15617 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015618
15619 if($TargetArch) {
15620 return $TargetArch;
15621 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015622 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015623 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015624 return $CPU_ARCH{$LibVersion};
15625 }
15626 elsif($UsedDump{$LibVersion}{"V"})
15627 { # old-version dumps
15628 return "unknown";
15629 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015630
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015631 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015632}
15633
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015634sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015635{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015636 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015638 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015639 if(getArch(1) ne getArch(2)
15640 or getArch(1) eq "unknown"
15641 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015642 { # don't show architecture in the header
15643 $ArchInfo="";
15644 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015645 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015646 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015647 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015648 }
15649 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015650 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015651 }
15652 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015653 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015654 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015655
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015656 my $V1 = $Descriptor{1}{"Version"};
15657 my $V2 = $Descriptor{2}{"Version"};
15658
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015659 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15660 {
15661 my $M1 = $UsedDump{1}{"M"};
15662 my $M2 = $UsedDump{2}{"M"};
15663
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015664 my $M1S = $M1;
15665 my $M2S = $M2;
15666
15667 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15668 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15669
15670 if($M1S eq $M2S
15671 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015672 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015673 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15674 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015675 }
15676 else
15677 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015678 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15679 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015680 }
15681 }
15682 else
15683 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015684 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015685 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015686 }
15687
15688 $Title .= $ArchInfo;
15689
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015691 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015693 $Title = "<h1>".$Title."</h1>\n";
15694 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015695}
15696
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015697sub get_CheckedHeaders($)
15698{
15699 my $LibVersion = $_[0];
15700
15701 my @Headers = ();
15702
15703 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15704 {
15705 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015706
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015707 if(not is_target_header($File, $LibVersion)) {
15708 next;
15709 }
15710
15711 if(skipHeader($File, $LibVersion)) {
15712 next;
15713 }
15714
15715 push(@Headers, $Path);
15716 }
15717
15718 return @Headers;
15719}
15720
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721sub get_SourceInfo()
15722{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015723 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015724
15725 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015726 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015727 $CheckedHeaders = "<a name='Headers'></a>";
15728 if($OldStyle) {
15729 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15730 }
15731 else {
15732 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15733 }
15734 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015735 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 +040015736 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015737 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15738 my $Name = get_filename($Identity);
15739 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15740 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015741 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015742 $CheckedHeaders .= "</div>\n";
15743 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015745
15746 if(my @Sources = keys(%{$Registered_Sources{1}}))
15747 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015748 $CheckedSources = "<a name='Sources'></a>";
15749 if($OldStyle) {
15750 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15751 }
15752 else {
15753 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15754 }
15755 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015756 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15757 {
15758 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15759 my $Name = get_filename($Identity);
15760 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15761 $CheckedSources .= $Name.$Comment."<br/>\n";
15762 }
15763 $CheckedSources .= "</div>\n";
15764 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15765 }
15766
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015767 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015768 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015769 $CheckedLibs = "<a name='Libs'></a>";
15770 if($OldStyle) {
15771 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15772 }
15773 else {
15774 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15775 }
15776 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15777 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015778 $CheckedLibs .= $Library."<br/>\n";
15779 }
15780 $CheckedLibs .= "</div>\n";
15781 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015783
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015784 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15785}
15786
15787sub get_ObjTitle()
15788{
15789 if(defined $UsedDump{1}{"DWARF"}) {
15790 return "Objects";
15791 }
15792 else {
15793 return ucfirst($SLIB_TYPE)." Libraries";
15794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015795}
15796
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015797sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015798{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015799 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015800 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015801
15802 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015803 {
15804 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015805 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015807 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015809 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015810 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015811
15812 if($Severity ne $TargetSeverity) {
15813 next;
15814 }
15815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015816 if($Kinds_Target{$Kind}{$Target}) {
15817 next;
15818 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015819
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 $Kinds_Target{$Kind}{$Target} = 1;
15821 $Type_Problems_Count += 1;
15822 }
15823 }
15824 }
15825 return $Type_Problems_Count;
15826}
15827
15828sub get_Summary($)
15829{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015830 my $Level = $_[0];
15831 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015832 $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 +040015833 %{$RESULT{$Level}} = (
15834 "Problems"=>0,
15835 "Warnings"=>0,
15836 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015837 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015838 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015839 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015840 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015841 {
15842 if(not defined $CompatRules{$Level}{$Kind})
15843 { # unknown rule
15844 if(not $UnknownRules{$Level}{$Kind})
15845 { # only one warning
15846 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15847 $UnknownRules{$Level}{$Kind}=1;
15848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015849 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015850 }
15851 }
15852 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015853 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15854 {
15855 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15856 {
15857 if(not defined $CompatRules{$Level}{$Kind})
15858 { # unknown rule
15859 if(not $UnknownRules{$Level}{$Kind})
15860 { # only one warning
15861 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15862 $UnknownRules{$Level}{$Kind}=1;
15863 }
15864 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15865 }
15866 }
15867 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015869 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015870 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015871 {
15872 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15873 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015874 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015876 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015877 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015878 $Added += 1;
15879 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015880 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015881 {
15882 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015883 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015884 }
15885 else
15886 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015887 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015888 $I_Other += 1;
15889 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015890 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015891 $I_Problems_High += 1;
15892 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015893 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015894 $I_Problems_Medium += 1;
15895 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015896 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015897 $I_Problems_Low += 1;
15898 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015899 if(($Severity ne "Low" or $StrictCompat)
15900 and $Severity ne "Safe") {
15901 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015902 }
15903 }
15904 }
15905 }
15906 }
15907 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015908
15909 my %MethodTypeIndex = ();
15910
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015911 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015912 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015913 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15914 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915 {
15916 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15917 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015918 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15919 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015920 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015921 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15922 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015923
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015924 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15925 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015926 next;
15927 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015928 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15929 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15930
15931 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015932
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015933 if(($Severity ne "Low" or $StrictCompat)
15934 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015935 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015936 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015937 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015938 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015939 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015940 }
15941 }
15942 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015943 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015946 }
15947 }
15948 }
15949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015950
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015951 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15952 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15953 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15954 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015955
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015956 # changed and removed public symbols
15957 my $SCount = keys(%{$CheckedSymbols{$Level}});
15958 if($ExtendedCheck)
15959 { # don't count external_func_0 for constants
15960 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015962 if($SCount)
15963 {
15964 my %Weight = (
15965 "High" => 100,
15966 "Medium" => 50,
15967 "Low" => 25
15968 );
15969 foreach (keys(%{$TotalAffected{$Level}})) {
15970 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015971 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015972 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015974 else {
15975 $RESULT{$Level}{"Affected"} = 0;
15976 }
15977
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15979 if($RESULT{$Level}{"Affected"}>=100) {
15980 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015981 }
15982
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015983 $RESULT{$Level}{"Problems"} += $Removed;
15984 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015985 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015986 if($StrictCompat) {
15987 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15988 }
15989 else {
15990 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015992
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015993 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015994 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015995 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015996 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015997 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015998 if($Severity eq "Safe")
15999 {
16000 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016001 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016002 elsif($Severity eq "Low")
16003 {
16004 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016005 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016006 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016007 }
16008
16009 if($C_Problems_Low)
16010 {
16011 if($StrictCompat) {
16012 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
16013 }
16014 else {
16015 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016016 }
16017 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016018 if($RESULT{$Level}{"Problems"}
16019 and $RESULT{$Level}{"Affected"}) {
16020 $RESULT{$Level}{"Verdict"} = "incompatible";
16021 }
16022 else {
16023 $RESULT{$Level}{"Verdict"} = "compatible";
16024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016025
16026 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
16027 if(not $TotalTypes)
16028 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016029 $TotalTypes = keys(%{$TName_Tid{1}});
16030 }
16031
16032 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
16033 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016034 my ($ClangV1, $ClangV2) = ($CLANG_VERSION{1}, $CLANG_VERSION{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016035
16036 my ($TestInfo, $TestResults, $Problem_Summary) = ();
16037
16038 if($ReportFormat eq "xml")
16039 { # XML
16040 # test info
16041 $TestInfo .= " <library>$TargetLibraryName</library>\n";
16042 $TestInfo .= " <version1>\n";
16043 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016044 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016045 if($GccV1) {
16046 $TestInfo .= " <gcc>$GccV1</gcc>\n";
16047 }
16048 elsif($ClangV1) {
16049 $TestInfo .= " <clang>$ClangV1</clang>\n";
16050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016051 $TestInfo .= " </version1>\n";
16052
16053 $TestInfo .= " <version2>\n";
16054 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016055 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016056 if($GccV2) {
16057 $TestInfo .= " <gcc>$GccV2</gcc>\n";
16058 }
16059 elsif($ClangV2) {
16060 $TestInfo .= " <clang>$ClangV2</clang>\n";
16061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016062 $TestInfo .= " </version2>\n";
16063 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
16064
16065 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016066 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016067 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016068 $TestResults .= " <headers>\n";
16069 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
16070 {
16071 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
16072 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16073 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16074 }
16075 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016076 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016077
16078 if(my @Sources = keys(%{$Registered_Sources{1}}))
16079 {
16080 $TestResults .= " <sources>\n";
16081 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16082 {
16083 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16084 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16085 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16086 }
16087 $TestResults .= " </sources>\n";
16088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016089
16090 $TestResults .= " <libs>\n";
16091 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16092 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016093 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016094 $TestResults .= " <name>$Library</name>\n";
16095 }
16096 $TestResults .= " </libs>\n";
16097
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016098 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016099 $TestResults .= " <types>".$TotalTypes."</types>\n";
16100
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016101 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16102 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016103 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16104
16105 # problem summary
16106 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16107 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16108
16109 $Problem_Summary .= " <problems_with_types>\n";
16110 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16111 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16112 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16113 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16114 $Problem_Summary .= " </problems_with_types>\n";
16115
16116 $Problem_Summary .= " <problems_with_symbols>\n";
16117 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16118 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16119 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016120 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016121 $Problem_Summary .= " </problems_with_symbols>\n";
16122
16123 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016124 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016125 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016127 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16128
16129 return ($TestInfo.$TestResults.$Problem_Summary, "");
16130 }
16131 else
16132 { # HTML
16133 # test info
16134 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016135 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016136
16137 if($TargetComponent eq "library") {
16138 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16139 }
16140 else {
16141 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143
16144 my (@VInf1, @VInf2, $AddTestInfo) = ();
16145 if($Arch1 ne "unknown"
16146 and $Arch2 ne "unknown")
16147 { # CPU arch
16148 if($Arch1 eq $Arch2)
16149 { # go to the separate section
Andrey Ponomarenko19b61de2016-08-31 19:45:06 +030016150 $AddTestInfo .= "<tr><th>Arch</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 }
16152 else
16153 { # go to the version number
16154 push(@VInf1, showArch($Arch1));
16155 push(@VInf2, showArch($Arch2));
16156 }
16157 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016158 if($Level eq "Binary"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016159 and $OStarget ne "windows")
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016160 {
16161 if($GccV1 ne "unknown"
16162 and $GccV2 ne "unknown")
16163 { # GCC version
16164 if($GccV1 eq $GccV2)
16165 { # go to the separate section
16166 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16167 }
16168 else
16169 { # go to the version number
16170 push(@VInf1, "gcc ".$GccV1);
16171 push(@VInf2, "gcc ".$GccV2);
16172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016174 elsif($ClangV1
16175 and $ClangV2)
16176 { # Clang version
16177 if($ClangV1 eq $ClangV2)
16178 { # go to the separate section
16179 $AddTestInfo .= "<tr><th>Clang Version</th><td>$ClangV1</td></tr>\n";
16180 }
16181 else
16182 { # go to the version number
16183 push(@VInf1, "clang ".$ClangV1);
16184 push(@VInf2, "clang ".$ClangV2);
16185 }
16186 }
16187 elsif($GccV1 ne "unknown" and $ClangV2)
16188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016189 push(@VInf1, "gcc ".$GccV1);
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016190 push(@VInf2, "clang ".$ClangV2);
16191 }
16192 elsif($ClangV1 and $GccV2 ne "unknown")
16193 {
16194 push(@VInf1, "clang ".$ClangV1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 push(@VInf2, "gcc ".$GccV2);
16196 }
16197 }
16198 # show long version names with GCC version and CPU architecture name (if different)
16199 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16200 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16201 $TestInfo .= $AddTestInfo;
16202 #if($COMMON_LANGUAGE{1}) {
16203 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16204 #}
16205 if($ExtendedCheck) {
16206 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16207 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016208 if($JoinReport)
16209 {
16210 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016211 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016212 }
Andrey Ponomarenkodd172162016-10-04 19:41:25 +030016213 elsif($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016214 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 }
16216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016217 $TestInfo .= "</table>\n";
16218
16219 # test results
16220 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016223 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016224 {
16225 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16226 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16227 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016228
16229 if(my @Sources = keys(%{$Registered_Sources{1}}))
16230 {
16231 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16232 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016234
16235 if(not $ExtendedCheck)
16236 {
16237 my $Libs_Link = "0";
16238 $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 +040016239 $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 +040016240 }
16241
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016242 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016243
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016244 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245 if($JoinReport) {
16246 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16247 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016248
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016249 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016250
16251 $TestResults .= "<tr><th>Compatibility</th>\n";
16252 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16253 {
16254 my $Cl = "incompatible";
16255 if($BC_Rate>=90) {
16256 $Cl = "warning";
16257 }
16258 elsif($BC_Rate>=80) {
16259 $Cl = "almost_compatible";
16260 }
16261
16262 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016263 }
16264 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016265 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016266 }
16267 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 $TestResults .= "</table>\n";
16269
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016271 # problem summary
16272 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016273 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16275
16276 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016277 if($Added>0)
16278 {
16279 if($JoinReport) {
16280 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16281 }
16282 else {
16283 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16284 }
16285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016287 $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 +040016288
16289 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016290 if($Removed>0)
16291 {
16292 if($JoinReport) {
16293 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16294 }
16295 else {
16296 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16297 }
16298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016300 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016301 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016302
16303 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016304 $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 +040016305 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016306 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016307 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308
16309 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016310 $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 +040016311 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016312 $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 +040016313
16314 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016315 $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 +040016316 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016317 $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 +040016318
16319 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016320 $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 +040016321 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016322 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016323 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016324
16325 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016326 $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 +040016327 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016328 $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 +040016329
16330 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016331 $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 +040016332 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016333 $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 +040016334
16335 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016336 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16337 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016339 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016340 $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 +040016341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016343 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016344 {
16345 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016346 $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 +030016347 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016348 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016349
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016350 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016351 {
16352 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016353 $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 +030016354 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016356
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016357 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016358 {
16359 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016360 $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 +030016361 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016362 }
16363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 $META_DATA .= "tool_version:$TOOL_VERSION";
16365 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016367 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16368 }
16369}
16370
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016371sub getStyle($$$)
16372{
16373 my ($Subj, $Act, $Num) = @_;
16374 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016375 "Added"=>"new",
16376 "Removed"=>"failed",
16377 "Safe"=>"passed",
16378 "Low"=>"warning",
16379 "Medium"=>"failed",
16380 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016381 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016382
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016383 if($Num>0) {
16384 return " class='".$Style{$Act}."'";
16385 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016386
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016387 return "";
16388}
16389
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016390sub show_number($)
16391{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016392 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016393 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016394 my $Num = cut_off_number($_[0], 2, 0);
16395 if($Num eq "0")
16396 {
16397 foreach my $P (3 .. 7)
16398 {
16399 $Num = cut_off_number($_[0], $P, 1);
16400 if($Num ne "0") {
16401 last;
16402 }
16403 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016404 }
16405 if($Num eq "0") {
16406 $Num = $_[0];
16407 }
16408 return $Num;
16409 }
16410 return $_[0];
16411}
16412
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016413sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016414{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016415 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016416 if($num!~/\./)
16417 {
16418 $num .= ".";
16419 foreach (1 .. $digs_to_cut-1) {
16420 $num .= "0";
16421 }
16422 }
16423 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16424 {
16425 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16426 $num .= "0";
16427 }
16428 }
16429 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16430 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16431 }
16432 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016433 if($z) {
16434 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016436 return $num;
16437}
16438
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016439sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016440{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016441 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016442 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016443
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016444 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016445 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16446 {
16447 my $Header = $Constants{1}{$Constant}{"Header"};
16448 if(not $Header)
16449 { # added
16450 $Header = $Constants{2}{$Constant}{"Header"}
16451 }
16452
16453 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16454 {
16455 if(not defined $CompatRules{$Level}{$Kind}) {
16456 next;
16457 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016458 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016459 next;
16460 }
16461 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016463 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 if($ReportFormat eq "xml")
16466 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016467 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016468 {
16469 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016470 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 {
16472 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016473 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16474 {
16475 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16476 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16477 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016478
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016479 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16480 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16481 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016482 if($Overcome) {
16483 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16484 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016485 $CHANGED_CONSTANTS .= " </problem>\n";
16486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 $CHANGED_CONSTANTS .= " </constant>\n";
16488 }
16489 $CHANGED_CONSTANTS .= " </header>\n";
16490 }
16491 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16492 }
16493 else
16494 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016495 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016496 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016497 {
16498 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016499 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016500 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016501 my $Report = "";
16502
16503 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16504 {
16505 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16506 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016507 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016508 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016509 }
16510 if($Report)
16511 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016512 $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 +030016513 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016514 $Report = insertIDs($Report);
16515 }
16516 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016517 }
16518 $CHANGED_CONSTANTS .= "<br/>\n";
16519 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016520 if($CHANGED_CONSTANTS)
16521 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016522 my $Title = "Problems with Constants, $TargetSeverity Severity";
16523 if($TargetSeverity eq "Safe")
16524 { # Safe Changes
16525 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016527 if($OldStyle) {
16528 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16529 }
16530 else {
16531 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16532 }
16533 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016534 }
16535 }
16536 return $CHANGED_CONSTANTS;
16537}
16538
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539sub getTitle($$$)
16540{
16541 my ($Header, $Library, $NameSpace) = @_;
16542 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016543
16544 # if($Library and $Library!~/\.\w+\Z/) {
16545 # $Library .= " (.$LIB_EXT)";
16546 # }
16547
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 if($Header and $Library)
16549 {
16550 $Title .= "<span class='h_name'>$Header</span>";
16551 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16552 }
16553 elsif($Library) {
16554 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16555 }
16556 elsif($Header) {
16557 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16558 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016559
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016560 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016561 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016562 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016563
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016564 return $Title;
16565}
16566
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016567sub get_Report_Added($)
16568{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016569 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016570 my $ADDED_INTERFACES = "";
16571 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016572 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016573 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016574 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016575 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016576 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 {
16578 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16579 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 if($Level eq "Source" and $ReportFormat eq "html")
16581 { # do not show library name in HTML report
16582 $DyLib = "";
16583 }
16584 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016585 }
16586 }
16587 }
16588 if($ReportFormat eq "xml")
16589 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016590 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 {
16592 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016593 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016594 {
16595 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016596 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016597 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16598 }
16599 $ADDED_INTERFACES .= " </library>\n";
16600 }
16601 $ADDED_INTERFACES .= " </header>\n";
16602 }
16603 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16604 }
16605 else
16606 { # HTML
16607 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016608 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016609 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016610 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016612 my %NameSpaceSymbols = ();
16613 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016614 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016616 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016618 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16619 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 foreach my $Interface (@SortedInterfaces)
16621 {
16622 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016623 my $Signature = get_Signature($Interface, 2);
16624 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016625 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016626 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016627 if($Interface=~/\A(_Z|\?)/)
16628 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016630 $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 +040016631 }
16632 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016633 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 }
16635 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016636 else
16637 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016638 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016639 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016640 }
16641 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016642 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016643 }
16644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016646 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 }
16649 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 if($ADDED_INTERFACES)
16651 {
16652 my $Anchor = "<a name='Added'></a>";
16653 if($JoinReport) {
16654 $Anchor = "<a name='".$Level."_Added'></a>";
16655 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016656 if($OldStyle) {
16657 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16658 }
16659 else {
16660 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16661 }
16662 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016663 }
16664 }
16665 return $ADDED_INTERFACES;
16666}
16667
16668sub get_Report_Removed($)
16669{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016671 my $REMOVED_INTERFACES = "";
16672 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016673 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016675 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016679 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16680 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 if($Level eq "Source" and $ReportFormat eq "html")
16682 { # do not show library name in HTML report
16683 $DyLib = "";
16684 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016685 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016686 }
16687 }
16688 }
16689 if($ReportFormat eq "xml")
16690 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016691 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 {
16693 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016694 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016695 {
16696 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016697 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16698 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 }
16700 $REMOVED_INTERFACES .= " </library>\n";
16701 }
16702 $REMOVED_INTERFACES .= " </header>\n";
16703 }
16704 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16705 }
16706 else
16707 { # HTML
16708 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016709 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016711 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016712 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016713 my %NameSpaceSymbols = ();
16714 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016715 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016716 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016717 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016718 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016719 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16720 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016721 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016722 {
16723 $Removed_Number += 1;
16724 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016725 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016727 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016728 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016729 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016730 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016731 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016732 $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 +040016733 }
16734 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016735 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 }
16737 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738 else
16739 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016740 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016741 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 }
16743 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016744 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 }
16746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016747 }
16748 }
16749 $REMOVED_INTERFACES .= "<br/>\n";
16750 }
16751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 if($REMOVED_INTERFACES)
16753 {
16754 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16755 if($JoinReport) {
16756 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16757 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016758 if($OldStyle) {
16759 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16760 }
16761 else {
16762 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16763 }
16764
16765 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 }
16767 }
16768 return $REMOVED_INTERFACES;
16769}
16770
16771sub getXmlParams($$)
16772{
16773 my ($Content, $Problem) = @_;
16774 return "" if(not $Content or not $Problem);
16775 my %XMLparams = ();
16776 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16777 {
16778 my $Macro = "\@".lc($Attr);
16779 if($Content=~/\Q$Macro\E/) {
16780 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16781 }
16782 }
16783 my @PString = ();
16784 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016785 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016786 }
16787 if(@PString) {
16788 return " ".join(" ", @PString);
16789 }
16790 else {
16791 return "";
16792 }
16793}
16794
16795sub addMarkup($)
16796{
16797 my $Content = $_[0];
16798 # auto-markup
16799 $Content=~s/\n[ ]*//; # spaces
16800 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16801 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016802 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016803 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16804 if($Content=~/\ANOTE:/)
16805 { # notes
16806 $Content=~s!(NOTE):!<b>$1</b>:!g;
16807 }
16808 else {
16809 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16810 }
16811 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16812 my @Keywords = (
16813 "void",
16814 "const",
16815 "static",
16816 "restrict",
16817 "volatile",
16818 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016819 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016820 );
16821 my $MKeys = join("|", @Keywords);
16822 foreach (@Keywords) {
16823 $MKeys .= "|non-".$_;
16824 }
16825 $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 +040016826
16827 # Markdown
16828 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16829 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 return $Content;
16831}
16832
16833sub applyMacroses($$$$)
16834{
16835 my ($Level, $Kind, $Content, $Problem) = @_;
16836 return "" if(not $Content or not $Problem);
16837 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16838 $Content = addMarkup($Content);
16839 # macros
16840 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16841 {
16842 my $Macro = "\@".lc($Attr);
16843 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016844 if(not defined $Value
16845 or $Value eq "") {
16846 next;
16847 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016848
16849 if(index($Content, $Macro)==-1) {
16850 next;
16851 }
16852
16853 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16854 and $Kind!~/_Type_/
16855 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016857 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016858 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016859 $Value = black_name($Value);
16860 }
16861 elsif($Value=~/\s/) {
16862 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16863 }
16864 elsif($Value=~/\A\d+\Z/
16865 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16866 { # bits to bytes
16867 if($Value % $BYTE_SIZE)
16868 { # bits
16869 if($Value==1) {
16870 $Value = "<b>".$Value."</b> bit";
16871 }
16872 else {
16873 $Value = "<b>".$Value."</b> bits";
16874 }
16875 }
16876 else
16877 { # bytes
16878 $Value /= $BYTE_SIZE;
16879 if($Value==1) {
16880 $Value = "<b>".$Value."</b> byte";
16881 }
16882 else {
16883 $Value = "<b>".$Value."</b> bytes";
16884 }
16885 }
16886 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016887 else
16888 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 $Value = "<b>".htmlSpecChars($Value)."</b>";
16890 }
16891 $Content=~s/\Q$Macro\E/$Value/g;
16892 }
16893
16894 if($Content=~/(\A|[^\@\w])\@\w/)
16895 {
16896 if(not $IncompleteRules{$Level}{$Kind})
16897 { # only one warning
16898 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16899 $IncompleteRules{$Level}{$Kind} = 1;
16900 }
16901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016902 return $Content;
16903}
16904
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016905sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016906{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016907 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016908 my $INTERFACE_PROBLEMS = "";
16909 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016910
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016913 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16914 if($SV and defined $CompatProblems{$Level}{$SN}) {
16915 next;
16916 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016917 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16918 my $DyLib = $Symbol_Library{1}{$Symbol};
16919 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16920 { # Symbol with Version
16921 $DyLib = $Symbol_Library{1}{$VSym};
16922 }
16923 if(not $DyLib)
16924 { # const global data
16925 $DyLib = "";
16926 }
16927 if($Level eq "Source" and $ReportFormat eq "html")
16928 { # do not show library name in HTML report
16929 $DyLib = "";
16930 }
16931
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016932 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016933 {
16934 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016935 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016936 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016937 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16938 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016939 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016940 if($Severity eq $TargetSeverity)
16941 {
16942 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16943 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 }
16945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 }
16947 }
16948 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016949
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 if($ReportFormat eq "xml")
16951 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016952 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016953 {
16954 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 {
16957 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016958 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16959 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 {
16961 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016962 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016963 {
16964 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16965 {
16966 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016967 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016968
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16970 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16971 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16972 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16973 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016974 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16975 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 $INTERFACE_PROBLEMS .= " </problem>\n";
16978 }
16979 }
16980 $INTERFACE_PROBLEMS .= " </symbol>\n";
16981 }
16982 $INTERFACE_PROBLEMS .= " </library>\n";
16983 }
16984 $INTERFACE_PROBLEMS .= " </header>\n";
16985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 }
16988 else
16989 { # HTML
16990 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016991 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016993 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016995 my (%NameSpaceSymbols, %NewSignature) = ();
16996 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016997 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016999 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017001 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030017002 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 +040017003 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017005 my $Signature = get_Signature($Symbol, 1);
17006 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030017008 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017009 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017010 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017012 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017013 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017014 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017015 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017016 }
17017 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17018 {
17019 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017020 $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 +040017021 $ProblemNum += 1;
17022 $ProblemsNum += 1;
17023 }
17024 }
17025 }
17026 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017027 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017029 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017030 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017031 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017033
17034 if($NameSpace)
17035 {
17036 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
17037 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017038 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017039
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017040 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
17041 if($OldStyle) {
17042 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
17043 }
17044 else {
17045 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17046 }
17047 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017048 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017049
17050 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017051 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017052 if($NameSpace) {
17053 $NSign = cut_Namespace($NSign, $NameSpace);
17054 }
17055 $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 +040017056 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017057
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017058 if($Symbol=~/\A(_Z|\?)/) {
17059 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
17060 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017061
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017062 $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 +040017063 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017064 }
17065 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017066 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 }
17068 }
17069 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017071 if($INTERFACE_PROBLEMS)
17072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017073 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
17074 my $Title = "Problems with Symbols, $TargetSeverity Severity";
17075 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017076 { # Safe Changes
17077 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017079 if($OldStyle) {
17080 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
17081 }
17082 else {
17083 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
17084 }
17085 $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 +040017086 }
17087 }
17088 return $INTERFACE_PROBLEMS;
17089}
17090
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017091sub cut_Namespace($$)
17092{
17093 my ($N, $Ns) = @_;
17094 $N=~s/\b\Q$Ns\E:://g;
17095 return $N;
17096}
17097
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017098sub get_Report_TypeProblems($$)
17099{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017100 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017101 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017102
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017103 my %ReportMap = ();
17104 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017105
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017106 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017108 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17109
17110 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017112 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017113 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017114 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017115 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017116
17117 if($Severity eq $TargetSeverity)
17118 {
17119 $ReportMap{$HeaderName}{$TypeName} = 1;
17120 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017124 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 if($ReportFormat eq "xml")
17127 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017128 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129 {
17130 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017131 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017132 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017133 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017134 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017135 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017136 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017137 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017139 $Kinds_Locations{$Kind}{$Location} = 1;
17140
17141 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17142 if($Kinds_Target{$Kind}{$Target}) {
17143 next;
17144 }
17145 $Kinds_Target{$Kind}{$Target} = 1;
17146
17147 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17149 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17150 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17151 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17152 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017153 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17154 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017156 $TYPE_PROBLEMS .= " </problem>\n";
17157 }
17158 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017159 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17160 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017161 $TYPE_PROBLEMS .= showVTables($TypeName);
17162 }
17163 $TYPE_PROBLEMS .= " </type>\n";
17164 }
17165 $TYPE_PROBLEMS .= " </header>\n";
17166 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017167 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017168 }
17169 else
17170 { # HTML
17171 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017172 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017173 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017174 my (%NameSpace_Type) = ();
17175 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017176 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017177 }
17178 foreach my $NameSpace (sort keys(%NameSpace_Type))
17179 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017180 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017181 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 +040017182 foreach my $TypeName (@SortedTypes)
17183 {
17184 my $ProblemNum = 1;
17185 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017186 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017187
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017188 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017189 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017190 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017191 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017192 $Kinds_Locations{$Kind}{$Location} = 1;
17193
17194 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17195 if($Kinds_Target{$Kind}{$Target}) {
17196 next;
17197 }
17198 $Kinds_Target{$Kind}{$Target} = 1;
17199
17200 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17202 {
17203 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017204 $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 +040017205 $ProblemNum += 1;
17206 $ProblemsNum += 1;
17207 }
17208 }
17209 }
17210 $ProblemNum -= 1;
17211 if($TYPE_REPORT)
17212 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017213 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017214 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017215 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017216 $ShowVTables = showVTables($TypeName);
17217 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017218
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017219 my $ShowType = show_Type($TypeName, 1, 1);
17220
17221 if($NameSpace)
17222 {
17223 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17224 $ShowType = cut_Namespace($ShowType, $NameSpace);
17225 $Affected = cut_Namespace($Affected, $NameSpace);
17226 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17227 }
17228
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017229 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17230 if($OldStyle) {
17231 $TYPE_PROBLEMS .= " ($ProblemNum)";
17232 }
17233 else {
17234 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17235 }
17236 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017237 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17238 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17239 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17240 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 }
17242 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017243 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017244 }
17245 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017246
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247 if($TYPE_PROBLEMS)
17248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017249 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17250 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017251 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017252 { # Safe Changes
17253 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017254 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017255 if($OldStyle) {
17256 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17257 }
17258 else {
17259 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17260 }
17261 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017262 }
17263 }
17264 return $TYPE_PROBLEMS;
17265}
17266
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017267sub show_Type($$$)
17268{
17269 my ($Name, $Html, $LibVersion) = @_;
17270 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17271 $TType = lc($TType);
17272 if($TType=~/struct|union|enum/) {
17273 $Name=~s/\A\Q$TType\E //g;
17274 }
17275 if($Html) {
17276 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17277 }
17278 else {
17279 $Name = $TType." ".$Name;
17280 }
17281 return $Name;
17282}
17283
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017284sub get_Anchor($$$)
17285{
17286 my ($Kind, $Level, $Severity) = @_;
17287 if($JoinReport)
17288 {
17289 if($Severity eq "Safe") {
17290 return "Other_".$Level."_Changes_In_".$Kind."s";
17291 }
17292 else {
17293 return $Kind."_".$Level."_Problems_".$Severity;
17294 }
17295 }
17296 else
17297 {
17298 if($Severity eq "Safe") {
17299 return "Other_Changes_In_".$Kind."s";
17300 }
17301 else {
17302 return $Kind."_Problems_".$Severity;
17303 }
17304 }
17305}
17306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017307sub showVTables($)
17308{
17309 my $TypeName = $_[0];
17310 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017311 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017312 if(defined $Type1{"VTable"}
17313 and keys(%{$Type1{"VTable"}}))
17314 {
17315 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017316 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 if(defined $Type2{"VTable"}
17318 and keys(%{$Type2{"VTable"}}))
17319 {
17320 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17321 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017322 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017324 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17325 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 }
17327 my $VTABLES = "";
17328 if($ReportFormat eq "xml")
17329 { # XML
17330 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017331 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017333 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017334 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17335 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017336 $VTABLES .= " </entry>\n";
17337 }
17338 $VTABLES .= " </vtable>\n\n";
17339 }
17340 else
17341 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017342 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017343 $VTABLES .= "<tr><th>Offset</th>";
17344 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017345 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017346 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017347 {
17348 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017349
17350 my $E1 = $Entries{$Index}{"E1"};
17351 my $E2 = $Entries{$Index}{"E2"};
17352
17353 if($E1 ne $E2
17354 and $E1!~/ 0x/
17355 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017356 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017357 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017358 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017359 $Color1 = " class='failed'";
17360 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017361 }
17362 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017363 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017364 }
17365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017366 $VTABLES .= "<tr><th>".$Index."</th>\n";
17367 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17368 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 }
17370 $VTABLES .= "</table><br/>\n";
17371 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017372 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017373 }
17374 return $VTABLES;
17375 }
17376 }
17377 return "";
17378}
17379
17380sub simpleVEntry($)
17381{
17382 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017383 if(not defined $VEntry
17384 or $VEntry eq "") {
17385 return "";
17386 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017387
17388 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017389 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17390 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17391 if($VEntry=~/\A_ZThn.+\Z/) {
17392 $VEntry = "non-virtual thunk";
17393 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017394 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017395 # support for old GCC versions
17396 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17397 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17398 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017399 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17400 return $VEntry;
17401}
17402
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017403sub adjustParamPos($$$)
17404{
17405 my ($Pos, $Symbol, $LibVersion) = @_;
17406 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17407 {
17408 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17409 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17410 {
17411 return $Pos-1;
17412 }
17413
17414 return $Pos;
17415 }
17416
17417 return undef;
17418}
17419
17420sub getParamPos($$$)
17421{
17422 my ($Name, $Symbol, $LibVersion) = @_;
17423
17424 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17425 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17426 {
17427 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17428 foreach (keys(%{$Info->{"Param"}}))
17429 {
17430 if($Info->{"Param"}{$_}{"name"} eq $Name)
17431 {
17432 return $_;
17433 }
17434 }
17435 }
17436
17437 return undef;
17438}
17439
17440sub getParamName($)
17441{
17442 my $Loc = $_[0];
17443 $Loc=~s/\->.*//g;
17444 return $Loc;
17445}
17446
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017447sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017449 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017450
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017451 my $LIMIT = 10;
17452 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017453 $LIMIT = $AffectLimit;
17454 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017455
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017456 my @Kinds = sort keys(%{$Kinds_Locations});
17457 my %KLocs = ();
17458 foreach my $Kind (@Kinds)
17459 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017460 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 +030017461 $KLocs{$Kind} = \@Locs;
17462 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017463
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017464 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017465 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017466 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017467 if(index($Symbol, "_Z")==0
17468 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017469 { # duplicated problems for C2 constructors, D2 and D0 destructors
17470 next;
17471 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017472
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017473 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017475 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017476 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017477 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017478 next;
17479 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017480
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017481 if(index($Symbol, "\@")!=-1
17482 or index($Symbol, "\$")!=-1)
17483 {
17484 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17485
17486 if($Level eq "Source")
17487 { # remove symbol version
17488 $Symbol = $SN;
17489 }
17490
17491 if($SV and defined $CompatProblems{$Level}{$SN}
17492 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17493 { # duplicated problems for versioned symbols
17494 next;
17495 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017496 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017497
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017498 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017499 if($Type_Name ne $Target_TypeName) {
17500 next;
17501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017502
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017503 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017504 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017505 }
17506 }
17507 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017508
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017509 %KLocs = (); # clear
17510
17511 my %SymSel = ();
17512 my $Num = 0;
17513 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017514 {
17515 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17516 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017517 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017518 {
17519 $SymSel{$Symbol}{"Loc"} = $Loc;
17520 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017521 last LOOP;
17522 }
17523 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017524
17525 $Num += 1;
17526
17527 if($Num>=$LIMIT) {
17528 last;
17529 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017530 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017532 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017533
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017534 if($ReportFormat eq "xml")
17535 { # XML
17536 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017537
17538 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017539 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017540 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017541 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017542
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017543 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017544 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017546 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017547 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017548 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017549 $Target .= " param=\"$PName\"";
17550 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017551 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017552 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017553 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017554 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017555 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017556 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017557 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017558
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017559 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017560 $Target .= " field=\"$1\"";
17561 }
17562
17563 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017564 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017565 $Affected .= " </symbol>\n";
17566 }
17567 $Affected .= " </affected>\n";
17568 }
17569 else
17570 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017571 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017572 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017573 my $Kind = $SymSel{$Symbol}{"Kind"};
17574 my $Loc = $SymSel{$Symbol}{"Loc"};
17575
17576 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017577 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017578 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017579 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17580
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017581 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017582 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017583 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017584
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017585 if(keys(%SymLocKind)>$LIMIT) {
17586 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017587 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017588
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017589 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017590 if($Affected)
17591 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017592 my $Num = keys(%SymLocKind);
17593 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017594 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017595 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017596 }
17597 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017599 return $Affected;
17600}
17601
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017602sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017603{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017604 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017605 if($L2=~/\A(retval|this)\b/
17606 and $L1!~/\A(retval|this)\b/)
17607 {
17608 if($L1!~/\-\>/) {
17609 return 1;
17610 }
17611 elsif($L2=~/\-\>/) {
17612 return 1;
17613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017614 }
17615 return 0;
17616}
17617
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017618sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017619{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017620 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017621
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017622 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017623
17624 my $Location_I = $Location;
17625 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017627 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017628
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017629 if($Kind eq "Overridden_Virtual_Method"
17630 or $Kind eq "Overridden_Virtual_Method_B") {
17631 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17632 }
17633 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17634 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017635 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017637 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17638 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017639 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17640 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17641
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017642 if($ClassName eq $Problem{"Type_Name"}) {
17643 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17644 }
17645 else {
17646 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17647 }
17648 }
17649 else
17650 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017651 my $TypeID = undef;
17652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017653 if($Location=~/retval/)
17654 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017655 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 push(@Sentence, "Field \'".$Location."\' in return value");
17657 }
17658 else {
17659 push(@Sentence, "Return value");
17660 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017661
17662 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017663 }
17664 elsif($Location=~/this/)
17665 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017666 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017667 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17668 }
17669 else {
17670 push(@Sentence, "\'this\' pointer");
17671 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017672
17673 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017674 }
17675 else
17676 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017677
17678 my $PName = getParamName($Location);
17679 my $PPos = getParamPos($PName, $Symbol, 1);
17680
17681 if(index($Location, "->")!=-1) {
17682 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017683 }
17684 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017685 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017686 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017687 if($PName) {
17688 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017689 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017690
17691 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17692 }
17693
17694 if($Location!~/this/)
17695 {
17696 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017697 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017698 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017699 push(@Sentence, "(pointer)");
17700 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017701 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017702 push(@Sentence, "(reference)");
17703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017704 }
17705 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017706
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017707 if($Location eq "this") {
17708 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17709 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017710 else
17711 {
17712 my $Location_T = $Location;
17713 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17714
17715 my $TypeID_Problem = $TypeID;
17716 if($Location_T) {
17717 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17718 }
17719
17720 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17721 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17722 }
17723 else {
17724 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017726 }
17727 }
17728 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017729 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017730 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 +040017731 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017732
17733 my $Sent = join(" ", @Sentence);
17734
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017735 $Sent=~s/->/./g;
17736
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017737 if($ReportFormat eq "xml")
17738 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017739 $Sent=~s/'//g;
17740 }
17741
17742 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017743}
17744
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017745sub getFieldType($$$)
17746{
17747 my ($Location, $TypeId, $LibVersion) = @_;
17748
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017749 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017750
17751 foreach my $Name (@Fields)
17752 {
17753 my %Info = get_BaseType($TypeId, $LibVersion);
17754
17755 foreach my $Pos (keys(%{$Info{"Memb"}}))
17756 {
17757 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17758 {
17759 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17760 last;
17761 }
17762 }
17763 }
17764
17765 return $TypeId;
17766}
17767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017768sub get_XmlSign($$)
17769{
17770 my ($Symbol, $LibVersion) = @_;
17771 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17772 my $Report = "";
17773 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17774 {
17775 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017776 my $Type = $Info->{"Param"}{$Pos}{"type"};
17777 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017778 foreach my $Typedef (keys(%ChangedTypedef))
17779 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017780 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17781 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017783 }
17784 $Report .= " <param pos=\"$Pos\">\n";
17785 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017786 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017787 $Report .= " </param>\n";
17788 }
17789 if(my $Return = $Info->{"Return"})
17790 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017791 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017792 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017793 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794 $Report .= " </retval>\n";
17795 }
17796 return $Report;
17797}
17798
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017799sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017800{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017801 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017802 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017803 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017804 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017805 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17806 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017807 next;
17808 }
17809 $Report .= " <symbol name=\"$Symbol\">\n";
17810 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017811 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017812 {
17813 if(defined $CompleteSignature{1}{$Symbol}
17814 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17815 {
17816 $P1 = get_XmlSign($Symbol, 1);
17817 $S1 = get_Signature($Symbol, 1);
17818 }
17819 elsif($Symbol=~/\A(_Z|\?)/) {
17820 $S1 = $tr_name{$Symbol};
17821 }
17822 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017823 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017824 {
17825 if(defined $CompleteSignature{2}{$Symbol}
17826 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17827 {
17828 $P2 = get_XmlSign($Symbol, 2);
17829 $S2 = get_Signature($Symbol, 2);
17830 }
17831 elsif($Symbol=~/\A(_Z|\?)/) {
17832 $S2 = $tr_name{$Symbol};
17833 }
17834 }
17835 if($S1)
17836 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017837 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017838 $Report .= $P1;
17839 $Report .= " </old>\n";
17840 }
17841 if($S2 and $S2 ne $S1)
17842 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017843 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017844 $Report .= $P2;
17845 $Report .= " </new>\n";
17846 }
17847 $Report .= " </symbol>\n";
17848 }
17849 $Report .= "</symbols_info>\n";
17850 return $Report;
17851}
17852
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017853sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017854{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017855 my ($Level, $Report) = @_;
17856 if($ReportFormat eq "xml") {
17857 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017858 }
17859 if($StdOut)
17860 { # --stdout option
17861 print STDOUT $Report;
17862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017863 else
17864 {
17865 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017866 mkpath(get_dirname($RPath));
17867
17868 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17869 print REPORT $Report;
17870 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017871 }
17872}
17873
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017874sub getReport($)
17875{
17876 my $Level = $_[0];
17877 if($ReportFormat eq "xml")
17878 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017879 if($Level eq "Join")
17880 {
17881 my $Report = "<reports>\n";
17882 $Report .= getReport("Binary");
17883 $Report .= getReport("Source");
17884 $Report .= "</reports>\n";
17885 return $Report;
17886 }
17887 else
17888 {
17889 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17890 my ($Summary, $MetaData) = get_Summary($Level);
17891 $Report .= $Summary."\n";
17892 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17893 $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 +040017894
17895 # additional symbols info (if needed)
17896 # $Report .= get_Report_SymbolsInfo($Level);
17897
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017898 $Report .= "</report>\n";
17899 return $Report;
17900 }
17901 }
17902 else
17903 { # HTML
17904 my $CssStyles = readModule("Styles", "Report.css");
17905 my $JScripts = readModule("Scripts", "Sections.js");
17906 if($Level eq "Join")
17907 {
17908 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17909 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017910 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017911 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17912 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 +040017913 my ($BSummary, $BMetaData) = get_Summary("Binary");
17914 my ($SSummary, $SMetaData) = get_Summary("Source");
17915 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 +030017916 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017917 <br/>
17918 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017919 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17920 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017921 </div>";
17922 $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>";
17923 $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 +030017924 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017925 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017926 return $Report;
17927 }
17928 else
17929 {
17930 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017931 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17932 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17933 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 +040017934 if($Level eq "Binary")
17935 {
17936 if(getArch(1) eq getArch(2)
17937 and getArch(1) ne "unknown") {
17938 $Description .= " on ".showArch(getArch(1));
17939 }
17940 }
17941 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 +030017942 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017943 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17944 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17945 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017946 $Report .= "</div>\n<br/><br/><br/>\n";
17947 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017948 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017949 return $Report;
17950 }
17951 }
17952}
17953
17954sub createReport()
17955{
17956 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017957 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017958 writeReport("Join", getReport("Join"));
17959 }
17960 elsif($DoubleReport)
17961 { # default
17962 writeReport("Binary", getReport("Binary"));
17963 writeReport("Source", getReport("Source"));
17964 }
17965 elsif($BinaryOnly)
17966 { # --binary
17967 writeReport("Binary", getReport("Binary"));
17968 }
17969 elsif($SourceOnly)
17970 { # --source
17971 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017972 }
17973}
17974
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017975sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017976{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017977 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017978
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017979 $Footer .= "<hr/>\n";
17980 $Footer .= "<div class='footer' align='right'>";
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030017981 $Footer .= "<i>Generated by <a href='".$HomePage{"Dev"}."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017982 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017983 $Footer .= "<br/>\n";
17984
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017985 return $Footer;
17986}
17987
17988sub get_Report_Problems($$)
17989{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017990 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017991
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017992 my $Report = get_Report_TypeProblems($Severity, $Level);
17993 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017994 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017995 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017996
17997 if($Severity eq "Low" or $Severity eq "Safe") {
17998 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017999 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030018000
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018001 if($ReportFormat eq "html")
18002 {
18003 if($Report)
18004 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018005 if($JoinReport)
18006 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018007 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018008 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
18009 }
18010 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018011 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018014 else
18015 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018016 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018017 $Report = "<a name=\'Other_Changes\'></a>".$Report;
18018 }
18019 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040018020 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018022 }
18023 }
18024 }
18025 return $Report;
18026}
18027
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018028sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018029{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018030 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030018031
18032 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
18033 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
18034 $Head .= "<head>\n";
18035 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
18036 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
18037 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
18038 $Head .= "<title>$Title</title>\n";
18039 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
18040 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
18041 $Head .= "</head>\n";
18042
18043 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018044}
18045
18046sub insertIDs($)
18047{
18048 my $Text = $_[0];
18049 while($Text=~/CONTENT_ID/)
18050 {
18051 if(int($Content_Counter)%2) {
18052 $ContentID -= 1;
18053 }
18054 $Text=~s/CONTENT_ID/c_$ContentID/;
18055 $ContentID += 1;
18056 $Content_Counter += 1;
18057 }
18058 return $Text;
18059}
18060
18061sub checkPreprocessedUnit($)
18062{
18063 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018064 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018065 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018066 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018067
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018068 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018069 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018070 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018071 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018072 chomp($Line);
18073 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018074 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018075 $CurHeader = path_format($1, $OSgroup);
18076 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018077 $CurClass = "";
18078
18079 if(index($CurHeader, $TMP_DIR)==0) {
18080 next;
18081 }
18082
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018083 if(substr($CurHeaderName, 0, 1) eq "<")
18084 { # <built-in>, <command-line>, etc.
18085 $CurHeaderName = "";
18086 $CurHeader = "";
18087 }
18088
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018089 if($ExtraInfo)
18090 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018091 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018092 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18093 }
18094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018095 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018096 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018097 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018098 if($CurHeaderName)
18099 {
18100 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18101 and not $Registered_Headers{$Version}{$CurHeader})
18102 { # not a target
18103 next;
18104 }
18105 if(not is_target_header($CurHeaderName, 1)
18106 and not is_target_header($CurHeaderName, 2))
18107 { # user-defined header
18108 next;
18109 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018110 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018111 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018112
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018113 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018114 {
18115 my ($Name, $Value) = ($1, $2);
18116 if(not $Constants{$Version}{$Name}{"Access"})
18117 {
18118 $Constants{$Version}{$Name}{"Access"} = "public";
18119 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018120 if($CurHeaderName) {
18121 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18122 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018123 }
18124 }
18125 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18126 $Constants{$Version}{$1}{"Access"} = "private";
18127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018128 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018129 else
18130 {
18131 if(defined $ExtraDump)
18132 {
18133 if($Line=~/(\w+)\s*\(/)
18134 { # functions
18135 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18136 }
18137 #elsif($Line=~/(\w+)\s*;/)
18138 #{ # data
18139 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18140 #}
18141 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18142 $CurClass = $2;
18143 }
18144 }
18145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018146 }
18147 close(PREPROC);
18148 foreach my $Constant (keys(%{$Constants{$Version}}))
18149 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018150 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18151 {
18152 delete($Constants{$Version}{$Constant});
18153 next;
18154 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018155 if(not $ExtraDump and ($Constant=~/_h\Z/i
18156 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018157 { # skip
18158 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018159 }
18160 else {
18161 delete($Constants{$Version}{$Constant}{"Access"});
18162 }
18163 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018164 if($Debug)
18165 {
18166 mkpath($DEBUG_PATH{$Version});
18167 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018169}
18170
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018171sub uncoverConstant($$)
18172{
18173 my ($LibVersion, $Constant) = @_;
18174 return "" if(not $LibVersion or not $Constant);
18175 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18176 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18177 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18178 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018179
18180 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018181 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018182 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18183 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018184 {
18185 push(@RecurConstant, $Constant);
18186 my $Uncovered = uncoverConstant($LibVersion, $Value);
18187 if($Uncovered ne "") {
18188 $Value = $Uncovered;
18189 }
18190 pop(@RecurConstant);
18191 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018192
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018193 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018194 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018195 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18196 }
18197 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18198}
18199
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018200sub simpleConstant($$)
18201{
18202 my ($LibVersion, $Value) = @_;
18203 if($Value=~/\W/)
18204 {
18205 my $Value_Copy = $Value;
18206 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18207 {
18208 my $Word = $1;
18209 if($Value!~/$Word\s*\(/)
18210 {
18211 my $Val = uncoverConstant($LibVersion, $Word);
18212 if($Val ne "")
18213 {
18214 $Value=~s/\b$Word\b/$Val/g;
18215 }
18216 }
18217 }
18218 }
18219 return $Value;
18220}
18221
18222sub computeValue($)
18223{
18224 my $Value = $_[0];
18225
18226 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18227 return $1;
18228 }
18229
18230 if($Value=~/\A[\d\-\+()]+\Z/) {
18231 return eval($Value);
18232 }
18233
18234 return $Value;
18235}
18236
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018237my %IgnoreConstant = map {$_=>1} (
18238 "VERSION",
18239 "VERSIONCODE",
18240 "VERNUM",
18241 "VERS_INFO",
18242 "PATCHLEVEL",
18243 "INSTALLPREFIX",
18244 "VBUILD",
18245 "VPATCH",
18246 "VMINOR",
18247 "BUILD_STRING",
18248 "BUILD_TIME",
18249 "PACKAGE_STRING",
18250 "PRODUCTION",
18251 "CONFIGURE_COMMAND",
18252 "INSTALLDIR",
18253 "BINDIR",
18254 "CONFIG_FILE_PATH",
18255 "DATADIR",
18256 "EXTENSION_DIR",
18257 "INCLUDE_PATH",
18258 "LIBDIR",
18259 "LOCALSTATEDIR",
18260 "SBINDIR",
18261 "SYSCONFDIR",
18262 "RELEASE",
18263 "SOURCE_ID",
18264 "SUBMINOR",
18265 "MINOR",
18266 "MINNOR",
18267 "MINORVERSION",
18268 "MAJOR",
18269 "MAJORVERSION",
18270 "MICRO",
18271 "MICROVERSION",
18272 "BINARY_AGE",
18273 "INTERFACE_AGE",
18274 "CORE_ABI",
18275 "PATCH",
18276 "COPYRIGHT",
18277 "TIMESTAMP",
18278 "REVISION",
18279 "PACKAGE_TAG",
18280 "PACKAGEDATE",
18281 "NUMVERSION",
18282 "Release",
18283 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018284);
18285
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018286sub constantFilter($$$)
18287{
18288 my ($Name, $Value, $Level) = @_;
18289
18290 if($Level eq "Binary")
18291 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018292 if($Name=~/_t\Z/)
18293 { # __malloc_ptr_t
18294 return 1;
18295 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018296 foreach (keys(%IgnoreConstant))
18297 {
18298 if($Name=~/(\A|_)$_(_|\Z)/)
18299 { # version
18300 return 1;
18301 }
18302 if(/\A[A-Z].*[a-z]\Z/)
18303 {
18304 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18305 { # version
18306 return 1;
18307 }
18308 }
18309 }
18310 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18311 { # version
18312 return 1;
18313 }
18314 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18315 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18316 return 1;
18317 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018318
18319 if($Value=~/\A["'].*['"]/i)
18320 { # string
18321 return 0;
18322 }
18323
18324 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18325 { # static int gcry_pth_init
18326 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018327 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018328 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018329 return 1;
18330 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018331 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018332 { # foo(p)
18333 return 1;
18334 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018335 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018336 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018337 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018338 return 1;
18339 }
18340 }
18341
18342 return 0;
18343}
18344
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018345sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018346{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018347 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018348 foreach my $Constant (keys(%{$Constants{1}}))
18349 {
18350 if($SkipConstants{1}{$Constant})
18351 { # skipped by the user
18352 next;
18353 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018354
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018355 if(my $Header = $Constants{1}{$Constant}{"Header"})
18356 {
18357 if(not is_target_header($Header, 1)
18358 and not is_target_header($Header, 2))
18359 { # user-defined header
18360 next;
18361 }
18362 }
18363 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018364 next;
18365 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018366
18367 my $Old_Value = uncoverConstant(1, $Constant);
18368
18369 if(constantFilter($Constant, $Old_Value, $Level))
18370 { # separate binary and source problems
18371 next;
18372 }
18373
18374 if(not defined $Constants{2}{$Constant}{"Value"})
18375 { # removed
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018376 if(not defined $SkipRemovedConstants)
18377 {
18378 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18379 "Target"=>$Constant,
18380 "Old_Value"=>$Old_Value );
18381 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018382 next;
18383 }
18384
18385 if($Constants{2}{$Constant}{"Value"} eq "")
18386 { # empty value
18387 # TODO: implement a rule
18388 next;
18389 }
18390
18391 my $New_Value = uncoverConstant(2, $Constant);
18392
18393 my $Old_Value_Pure = $Old_Value;
18394 my $New_Value_Pure = $New_Value;
18395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018396 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18397 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18398 $New_Value_Pure=~s/(\W)\s+/$1/g;
18399 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018400
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018401 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018402
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018403 if($New_Value_Pure ne $Old_Value_Pure)
18404 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018405 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18406 { # complex values
18407 next;
18408 }
18409 if(computeValue($Old_Value) eq computeValue($New_Value))
18410 { # expressions
18411 next;
18412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018413 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18414 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18415 next;
18416 }
18417 if($Old_Value eq "0" and $New_Value eq "NULL")
18418 { # 0 => NULL
18419 next;
18420 }
18421 if($Old_Value eq "NULL" and $New_Value eq "0")
18422 { # NULL => 0
18423 next;
18424 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018425 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018426 "Target"=>$Constant,
18427 "Old_Value"=>$Old_Value,
18428 "New_Value"=>$New_Value );
18429 }
18430 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018431
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030018432 if(defined $SkipAddedConstants) {
18433 return;
18434 }
18435
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018436 foreach my $Constant (keys(%{$Constants{2}}))
18437 {
18438 if(not defined $Constants{1}{$Constant}{"Value"})
18439 {
18440 if($SkipConstants{2}{$Constant})
18441 { # skipped by the user
18442 next;
18443 }
18444
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018445 if(my $Header = $Constants{2}{$Constant}{"Header"})
18446 {
18447 if(not is_target_header($Header, 1)
18448 and not is_target_header($Header, 2))
18449 { # user-defined header
18450 next;
18451 }
18452 }
18453 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018454 next;
18455 }
18456
18457 my $New_Value = uncoverConstant(2, $Constant);
18458 if(not defined $New_Value or $New_Value eq "") {
18459 next;
18460 }
18461
18462 if(constantFilter($Constant, $New_Value, $Level))
18463 { # separate binary and source problems
18464 next;
18465 }
18466
18467 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18468 "Target"=>$Constant,
18469 "New_Value"=>$New_Value );
18470 }
18471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018472}
18473
18474sub convert_integer($)
18475{
18476 my $Value = $_[0];
18477 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018478 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018479 return hex($Value);
18480 }
18481 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018482 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018483 return oct($Value);
18484 }
18485 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018486 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018487 return oct($Value);
18488 }
18489 else {
18490 return $Value;
18491 }
18492}
18493
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018494sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018495{
18496 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018497 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018498 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 {
18500 if($LibVersion==1)
18501 {
18502 printMsg("WARNING", "checking headers only");
18503 $CheckHeadersOnly = 1;
18504 }
18505 else {
18506 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18507 }
18508 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018509
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018510 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018511 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018512 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018513
18514 if($CheckUndefined)
18515 {
18516 my %UndefinedLibs = ();
18517
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018518 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18519
18520 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018521 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018522 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018523 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018524 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018525 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018526 if($Symbol_Library{$LibVersion}{$Symbol}
18527 or $DepSymbol_Library{$LibVersion}{$Symbol})
18528 { # exported by target library
18529 next;
18530 }
18531 if(index($Symbol, '@')!=-1)
18532 { # exported default symbol version (@@)
18533 $Symbol=~s/\@/\@\@/;
18534 if($Symbol_Library{$LibVersion}{$Symbol}
18535 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18536 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018537 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018538 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018539 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18540 $UndefinedLibs{$Path} = 1;
18541 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018542 }
18543 }
18544 }
18545 if($ExtraInfo)
18546 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018547 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018548 {
18549 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018550 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018551 foreach (@Paths)
18552 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018553 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018554 my ($Dir, $Name) = separate_path($_);
18555
18556 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018557 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018558 }
18559
18560 $Name = parse_libname($Name, "name", $OStarget);
18561 $Name=~s/\Alib//;
18562
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018563 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018564 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018565
18566 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18567 {
18568 $LibString = " -L".esc($Dir).$LibString;
18569 }
18570
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018571 writeFile($ExtraInfo."/libs-string", $LibString);
18572 }
18573 }
18574 }
18575
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018576 if($ExtraInfo) {
18577 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18578 }
18579
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018580 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018581 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018582 if($#LibPaths!=-1)
18583 {
18584 if(not keys(%{$Symbol_Library{$LibVersion}}))
18585 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018586 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018587 printMsg("WARNING", "checking headers only");
18588 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018589 }
18590 }
18591 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018592
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018593 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018594 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018595}
18596
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018597my %Prefix_Lib_Map=(
18598 # symbols for autodetecting library dependencies (by prefix)
18599 "pthread_" => ["libpthread"],
18600 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18601 "cairo_" => ["libcairo"],
18602 "gtk_" => ["libgtk-x11-2.0"],
18603 "atk_" => ["libatk-1.0"],
18604 "gdk_" => ["libgdk-x11-2.0"],
18605 "gl" => ["libGL"],
18606 "glu" => ["libGLU"],
18607 "popt" => ["libpopt"],
18608 "Py" => ["libpython"],
18609 "jpeg_" => ["libjpeg"],
18610 "BZ2_" => ["libbz2"],
18611 "Fc" => ["libfontconfig"],
18612 "Xft" => ["libXft"],
18613 "SSL_" => ["libssl"],
18614 "sem_" => ["libpthread"],
18615 "snd_" => ["libasound"],
18616 "art_" => ["libart_lgpl_2"],
18617 "dbus_g" => ["libdbus-glib-1"],
18618 "GOMP_" => ["libgomp"],
18619 "omp_" => ["libgomp"],
18620 "cms" => ["liblcms"]
18621);
18622
18623my %Pattern_Lib_Map=(
18624 "SL[a-z]" => ["libslang"]
18625);
18626
18627my %Symbol_Lib_Map=(
18628 # symbols for autodetecting library dependencies (by name)
18629 "pow" => "libm",
18630 "fmod" => "libm",
18631 "sin" => "libm",
18632 "floor" => "libm",
18633 "cos" => "libm",
18634 "dlopen" => "libdl",
18635 "deflate" => "libz",
18636 "inflate" => "libz",
18637 "move_panel" => "libpanel",
18638 "XOpenDisplay" => "libX11",
18639 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018640 "clock_gettime" => "librt",
18641 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018642);
18643
18644sub find_SymbolLibs($$)
18645{
18646 my ($LibVersion, $Symbol) = @_;
18647
18648 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18649 { # debug symbols
18650 return ();
18651 }
18652
18653 my %Paths = ();
18654
18655 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18656 {
18657 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18658 $Paths{$Path} = 1;
18659 }
18660 }
18661
18662 if(my $SymbolPrefix = getPrefix($Symbol))
18663 {
18664 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18665 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18666 }
18667
18668 if(not keys(%Paths))
18669 {
18670 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18671 {
18672 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18673 {
18674 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18675 $Paths{$Path} = 1;
18676 }
18677 }
18678 }
18679 }
18680
18681 if(not keys(%Paths))
18682 {
18683 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18684 {
18685 if($Symbol=~/\A$Prefix/)
18686 {
18687 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18688 {
18689 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18690 $Paths{$Path} = 1;
18691 }
18692 }
18693 }
18694 }
18695 }
18696
18697 if(not keys(%Paths))
18698 {
18699 if($SymbolPrefix)
18700 { # try to find a library by symbol prefix
18701 if($SymbolPrefix eq "inotify" and
18702 index($Symbol, "\@GLIBC")!=-1)
18703 {
18704 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18705 $Paths{$Path} = 1;
18706 }
18707 }
18708 else
18709 {
18710 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18711 $Paths{$Path} = 1;
18712 }
18713 }
18714 }
18715 }
18716
18717 if(my @Paths = keys(%Paths)) {
18718 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18719 }
18720 }
18721 return keys(%Paths);
18722}
18723
18724sub get_LibPath_Prefix($$)
18725{
18726 my ($LibVersion, $Prefix) = @_;
18727
18728 $Prefix = lc($Prefix);
18729 $Prefix=~s/[_]+\Z//g;
18730
18731 foreach ("-2", "2", "-1", "1", "")
18732 { # libgnome-2.so
18733 # libxml2.so
18734 # libdbus-1.so
18735 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18736 return $Path;
18737 }
18738 }
18739 return "";
18740}
18741
18742sub getPrefix($)
18743{
18744 my $Str = $_[0];
18745 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18746 { # XmuValidArea: Xmu
18747 return $1;
18748 }
18749 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18750 { # snfReadFont: snf
18751 return $1;
18752 }
18753 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18754 { # XRRTimes: XRR
18755 return $1;
18756 }
18757 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18758 { # H5HF_delete: H5
18759 return $1;
18760 }
18761 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18762 { # alarm_event_add: alarm_
18763 return $1;
18764 }
18765 elsif($Str=~/\A(([a-z])\2{1,})/i)
18766 { # ffopen
18767 return $1;
18768 }
18769 return "";
18770}
18771
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018772sub getSymbolSize($$)
18773{ # size from the shared library
18774 my ($Symbol, $LibVersion) = @_;
18775 return 0 if(not $Symbol);
18776 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18777 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18778 {
18779 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18780 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18781 {
18782 if($Size<0) {
18783 return -$Size;
18784 }
18785 }
18786 }
18787 return 0;
18788}
18789
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018790sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018791{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18792 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018793 my ($Name, $Type) = @_;
18794
18795 # single
18796 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018797 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018798 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018799 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018800 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018801
18802 # double
18803 if($Name=~/$DEFAULT_STD_PARMS/)
18804 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018805 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018806 {
18807 my ($ShortName, $FuncParams) = split_Signature($Name);
18808
18809 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18810 {
18811 if(index($FParam, "<")!=-1)
18812 {
18813 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18814 my $FParam_N = canonifyName($FParam, "T");
18815 if($FParam_N ne $FParam) {
18816 $Name=~s/\Q$FParam\E/$FParam_N/g;
18817 }
18818 }
18819 }
18820 }
18821 elsif($Type eq "T")
18822 {
18823 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18824
18825 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018826 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018827 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018828 my $FParam = $TParams[0];
18829 foreach my $Pos (1 .. $#TParams)
18830 {
18831 my $TParam = $TParams[$Pos];
18832 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18833 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18834 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018835 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018836 }
18837 }
18838 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018839 if($Type eq "S") {
18840 return formatName($Name, "S");
18841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018842 return $Name;
18843}
18844
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018845sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018846{
18847 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018848 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018849 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018850 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018851 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018852 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018853 next if($tr_name{$Symbol});
18854 $Symbol=~s/[\@\$]+(.*)\Z//;
18855 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018856 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018857 elsif(index($Symbol, "?")==0)
18858 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018859 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018860 }
18861 else
18862 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018863 $tr_name{$Symbol} = $Symbol;
18864 $mangled_name_gcc{$Symbol} = $Symbol;
18865 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 }
18867 }
18868 if($#MnglNames1 > -1)
18869 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018870 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018871 foreach my $MnglName (@MnglNames1)
18872 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018873 if(my $Unmangled = pop(@UnmangledNames))
18874 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018875 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018876 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18877 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18878 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018879 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018880 and $tr_name{$MnglName}=~/vtable for (.+)/)
18881 { # bind class name and v-table symbol
18882 my $ClassName = $1;
18883 $ClassVTable{$ClassName} = $MnglName;
18884 $VTableClass{$MnglName} = $ClassName;
18885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 }
18887 }
18888 }
18889 if($#MnglNames2 > -1)
18890 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018891 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018892 foreach my $MnglName (@MnglNames2)
18893 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018894 if(my $Unmangled = pop(@UnmangledNames))
18895 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018896 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018897 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 }
18900 }
18901 return \%tr_name;
18902}
18903
18904sub link_symbol($$$)
18905{
18906 my ($Symbol, $RunWith, $Deps) = @_;
18907 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18908 return 1;
18909 }
18910 if($Deps eq "+Deps")
18911 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018912 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018913 return 1;
18914 }
18915 }
18916 return 0;
18917}
18918
18919sub link_symbol_internal($$$)
18920{
18921 my ($Symbol, $RunWith, $Where) = @_;
18922 return 0 if(not $Where or not $Symbol);
18923 if($Where->{$RunWith}{$Symbol})
18924 { # the exact match by symbol name
18925 return 1;
18926 }
18927 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18928 { # indirect symbol version, i.e.
18929 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018930 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018931 if($Where->{$RunWith}{$VSym}) {
18932 return 1;
18933 }
18934 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018935 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018936 if($Sym and $Ver)
18937 { # search for the symbol with the same version
18938 # or without version
18939 if($Where->{$RunWith}{$Sym})
18940 { # old: foo@v|foo@@v
18941 # new: foo
18942 return 1;
18943 }
18944 if($Where->{$RunWith}{$Sym."\@".$Ver})
18945 { # old: foo|foo@@v
18946 # new: foo@v
18947 return 1;
18948 }
18949 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18950 { # old: foo|foo@v
18951 # new: foo@@v
18952 return 1;
18953 }
18954 }
18955 return 0;
18956}
18957
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018958sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018959{
18960 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018961 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018962 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018963 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018964 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018965 my $NM = get_CmdPath("nm");
18966 if(not $NM) {
18967 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018969 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018970 while(<APP>)
18971 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018972 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018973 push(@Imported, $1);
18974 }
18975 }
18976 close(APP);
18977 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018978 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018979 {
18980 my $DumpBinCmd = get_CmdPath("dumpbin");
18981 if(not $DumpBinCmd) {
18982 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18983 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018984 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018985 while(<APP>)
18986 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018987 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18988 push(@Imported, $1);
18989 }
18990 }
18991 close(APP);
18992 }
18993 else
18994 {
18995 my $ReadelfCmd = get_CmdPath("readelf");
18996 if(not $ReadelfCmd) {
18997 exitStatus("Not_Found", "can't find \"readelf\"");
18998 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018999 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019000 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019001 while(<APP>)
19002 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 if(defined $symtab)
19004 { # do nothing with symtab
19005 if(index($_, "'.dynsym'")!=-1)
19006 { # dynamic table
19007 $symtab = undef;
19008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019009 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019010 elsif(index($_, "'.symtab'")!=-1)
19011 { # symbol table
19012 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019013 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019014 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019015 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019016 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
19017 if($Ndx eq "UND")
19018 { # only imported symbols
19019 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 }
19021 }
19022 }
19023 close(APP);
19024 }
19025 return @Imported;
19026}
19027
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019028my %ELF_BIND = map {$_=>1} (
19029 "WEAK",
19030 "GLOBAL"
19031);
19032
19033my %ELF_TYPE = map {$_=>1} (
19034 "FUNC",
19035 "IFUNC",
19036 "OBJECT",
19037 "COMMON"
19038);
19039
19040my %ELF_VIS = map {$_=>1} (
19041 "DEFAULT",
19042 "PROTECTED"
19043);
19044
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019046{ # read the line of 'readelf' output corresponding to the symbol
19047 my @Info = split(/\s+/, $_[0]);
19048 # Num: Value Size Type Bind Vis Ndx Name
19049 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019050 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019051 shift(@Info); # spaces
19052 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019053
19054 if($#Info==7)
19055 { # UND SYMBOL (N)
19056 if($Info[7]=~/\(\d+\)/) {
19057 pop(@Info);
19058 }
19059 }
19060
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019061 if($#Info!=6)
19062 { # other lines
19063 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019064 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019065 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019066 return () if(not defined $ELF_BIND{$Info[3]});
19067 return () if(not defined $ELF_VIS{$Info[4]});
19068 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19069 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19070 return ();
19071 }
19072 if($OStarget eq "symbian")
19073 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19074 if(index($Info[6], "_._.absent_export_")!=-1)
19075 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19076 return ();
19077 }
19078 $Info[6]=~s/\@.+//g; # remove version
19079 }
19080 if(index($Info[2], "0x") == 0)
19081 { # size == 0x3d158
19082 $Info[2] = hex($Info[2]);
19083 }
19084 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019085}
19086
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019087sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019088{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019089 my ($LibVersion, $Name) = @_;
19090 return "" if(not $LibVersion or not $Name);
19091 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19092 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019093 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019094 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19095}
19096
19097sub get_LibPath_I($$)
19098{
19099 my ($LibVersion, $Name) = @_;
19100 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019101 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019102 if(-f $Name)
19103 { # absolute path
19104 return $Name;
19105 }
19106 else
19107 { # broken
19108 return "";
19109 }
19110 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019111 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019112 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019113 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019115 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019116 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019117 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019118 }
19119 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19120 { # ldconfig default paths
19121 return $DefaultPath;
19122 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019123 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019124 { # search in default linker directories
19125 # and then in all system paths
19126 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019127 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019128 }
19129 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019130 if(not defined $Cache{"checkSystemFiles"}) {
19131 checkSystemFiles();
19132 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019133 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19134 return $AllObjects[0];
19135 }
19136 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19137 {
19138 if($ShortName ne $Name)
19139 { # FIXME: check this case
19140 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19141 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019142 }
19143 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019144 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019145 # can't find
19146 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019147}
19148
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019149sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019150{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019151 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19152 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019153
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019154 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019155
19156 if(not $Real_Path)
19157 { # broken link
19158 return ();
19159 }
19160
19161 my $Lib_Name = get_filename($Real_Path);
19162
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019163 if($ExtraInfo)
19164 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019165 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019166 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019167 }
19168
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019169 if($IsNeededLib)
19170 {
19171 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19172 return ();
19173 }
19174 }
19175 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019176 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 push(@RecurLib, $Lib_Name);
19179 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019180 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19181
19182 if(not $IsNeededLib)
19183 { # special cases: libstdc++ and libc
19184 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19185 {
19186 if($ShortName eq "libstdc++")
19187 { # libstdc++.so.6
19188 $STDCXX_TESTING = 1;
19189 }
19190 elsif($ShortName eq "libc")
19191 { # libc-2.11.3.so
19192 $GLIBC_TESTING = 1;
19193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019194 }
19195 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019196 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019197 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019198 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019199 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019200 mkpath(get_dirname($DebugPath));
19201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019202 if($OStarget eq "macos")
19203 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019204 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019205 if(not $NM) {
19206 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019207 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019208 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019209 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019210 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019211 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019212 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019213 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019214 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019215 else
19216 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019217 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019219 while(<LIB>)
19220 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019221 if($CheckUndefined)
19222 {
19223 if(not $IsNeededLib)
19224 {
19225 if(/ U _([\w\$]+)\s*\Z/)
19226 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019227 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019228 next;
19229 }
19230 }
19231 }
19232
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019233 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019235 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019236 if($IsNeededLib)
19237 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019238 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019239 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019240 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19241 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019244 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019245 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019246 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19247 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019248 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19249 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019250 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019251 setLanguage($LibVersion, "C++");
19252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 }
19255 }
19256 }
19257 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019258
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019259 if($Deps)
19260 {
19261 if($LIB_TYPE eq "dynamic")
19262 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019263
19264 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019265 if(not $OtoolCmd) {
19266 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019267 }
19268
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019269 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19270 while(<LIB>)
19271 {
19272 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19273 and $1 ne $Lib_Path) {
19274 $NeededLib{$1} = 1;
19275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019276 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019277 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019279 }
19280 }
19281 elsif($OStarget eq "windows")
19282 { # Windows *.dll, *.lib
19283 my $DumpBinCmd = get_CmdPath("dumpbin");
19284 if(not $DumpBinCmd) {
19285 exitStatus("Not_Found", "can't find \"dumpbin\"");
19286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019287 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019288 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019289 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019290 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019291 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019292 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019293 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019294 else
19295 { # write to pipe
19296 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019298 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019299 {
19300 my $realname = undef;
19301 if($LIB_TYPE eq "dynamic")
19302 {
19303 # 1197 4AC 0000A620 SetThreadStackGuarantee
19304 # 1198 4AD SetThreadToken (forwarded to ...)
19305 # 3368 _o2i_ECPublicKey
19306 # 1 0 00005B30 ??0?N = ... (with pdb)
19307 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19308 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19309 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19310 { # dynamic, static and forwarded symbols
19311 $realname = $1;
19312 }
19313 }
19314 else
19315 { # static
19316 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19317 {
19318 # 16 IID_ISecurityInformation
19319 $realname = $1;
19320 }
19321 }
19322
19323 if($realname)
19324 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019325 if($IsNeededLib)
19326 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019327 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019328 {
19329 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19330 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019332 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019333 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019334 {
19335 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19336 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019337 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19338 {
19339 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19340 setLanguage($LibVersion, "C++");
19341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019343 }
19344 }
19345 }
19346 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019347
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019348 if($Deps)
19349 {
19350 if($LIB_TYPE eq "dynamic")
19351 { # dependencies
19352 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19353 while(<LIB>)
19354 {
19355 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19356 and $1 ne $Lib_Path) {
19357 $NeededLib{path_format($1, $OSgroup)} = 1;
19358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019359 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019360 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019362 }
19363 }
19364 else
19365 { # Unix; *.so, *.a
19366 # Symbian: *.dso, *.lib
19367 my $ReadelfCmd = get_CmdPath("readelf");
19368 if(not $ReadelfCmd) {
19369 exitStatus("Not_Found", "can't find \"readelf\"");
19370 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019371 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019372 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019373 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019374 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019375 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019376 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019377 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019378 else
19379 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019380 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019381 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019382 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019383 while(<LIB>)
19384 {
19385 if($LIB_TYPE eq "dynamic")
19386 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019387 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019388 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019389 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019390 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019391 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019392 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019393 # do nothing with symtab
19394 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019396 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019397 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019398 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 next;
19400 }
19401 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019402 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019403 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019404 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019405 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019406 if($CheckUndefined)
19407 {
19408 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019409 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019410 }
19411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019412 next;
19413 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019414 if($Bind eq "WEAK")
19415 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019416 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019417 if($Weak eq "-Weak")
19418 { # skip WEAK symbols
19419 next;
19420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019421 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019422 my $Short = $Symbol;
19423 $Short=~s/\@.+//g;
19424 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019425 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019426 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19427 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019428 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019429 if($IsNeededLib)
19430 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019431 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019432 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19434 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019437 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019438 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019439 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19440 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19441 if($Vers)
19442 {
19443 if($LIB_EXT eq "so")
19444 { # value
19445 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19446 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019449 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19450 {
19451 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19452 setLanguage($LibVersion, "C++");
19453 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019455 }
19456 }
19457 }
19458 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019459
19460 if($Deps and $LIB_TYPE eq "dynamic")
19461 { # dynamic library specifics
19462 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19463 open(LIB, $Cmd." |");
19464
19465 while(<LIB>)
19466 {
19467 if(/NEEDED.+\[([^\[\]]+)\]/)
19468 { # dependencies:
19469 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19470 $NeededLib{$1} = 1;
19471 }
19472 }
19473
19474 close(LIB);
19475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019476 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019477 if($Vers)
19478 {
19479 if(not $IsNeededLib and $LIB_EXT eq "so")
19480 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019481 my %Found = ();
19482
19483 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019484 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019485 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019486 next if(index($Symbol,"\@")==-1);
19487 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019488 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019489 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019490 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019491 if($Symbol_SameValue ne $Symbol
19492 and index($Symbol_SameValue,"\@")==-1)
19493 {
19494 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019495 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019496 last;
19497 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019498 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019499 }
19500 }
19501
19502 # default
19503 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19504 {
19505 next if(defined $Found{$Symbol});
19506 next if(index($Symbol,"\@\@")==-1);
19507
19508 if($Symbol=~/\A([^\@]*)\@\@/
19509 and not $SymVer{$LibVersion}{$1})
19510 {
19511 $SymVer{$LibVersion}{$1} = $Symbol;
19512 $Found{$Symbol} = 1;
19513 }
19514 }
19515
19516 # non-default
19517 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19518 {
19519 next if(defined $Found{$Symbol});
19520 next if(index($Symbol,"\@")==-1);
19521
19522 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19523 and not $SymVer{$LibVersion}{$1})
19524 {
19525 $SymVer{$LibVersion}{$1} = $Symbol;
19526 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019527 }
19528 }
19529 }
19530 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019531 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019533 foreach my $DyLib (sort keys(%NeededLib))
19534 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019535 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19536
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019537 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19538 {
19539 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19540 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19541 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019543 }
19544 }
19545 pop(@RecurLib);
19546 return $Library_Symbol{$LibVersion};
19547}
19548
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019549sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019550{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019551 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019552 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019553 return keys(%Prefixes);
19554}
19555
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019556sub get_prefixes_I($$)
19557{
19558 foreach my $P (@{$_[0]})
19559 {
19560 my @Parts = reverse(split(/[\/\\]+/, $P));
19561 my $Name = $Parts[0];
19562 foreach (1 .. $#Parts)
19563 {
19564 $_[1]->{$Name}{$P} = 1;
19565 last if($_>4 or $Parts[$_] eq "include");
19566 $Name = $Parts[$_].$SLASH.$Name;
19567 }
19568 }
19569}
19570
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019571sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019572{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019573 $Cache{"checkSystemFiles"} = 1;
19574
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019575 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019576
19577 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019578 {
19579 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019580
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019581 my @Files = cmd_find($DevelPath,"f");
19582 foreach my $Link (cmd_find($DevelPath,"l"))
19583 { # add symbolic links
19584 if(-f $Link) {
19585 push(@Files, $Link);
19586 }
19587 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019588
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019589 # search for headers in /usr/lib
19590 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19591 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19592 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019593
19594 # search for libraries in /usr/lib (including symbolic links)
19595 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19596 foreach my $Path (@Libs)
19597 {
19598 my $N = get_filename($Path);
19599 $SystemObjects{$N}{$Path} = 1;
19600 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019601 }
19602 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019603
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019604 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019606 next if(not -d $DevelPath);
19607 # search for all header files in the /usr/include
19608 # with or without extension (ncurses.h, QtCore, ...)
19609 push(@SysHeaders, cmd_find($DevelPath,"f"));
19610 foreach my $Link (cmd_find($DevelPath,"l"))
19611 { # add symbolic links
19612 if(-f $Link) {
19613 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019615 }
19616 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019617 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019618}
19619
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019620sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019621{
19622 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019623 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019624 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19625 {
19626 if(not -e $Dest) {
19627 exitStatus("Access_Error", "can't access \'$Dest\'");
19628 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019629 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019630 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19631 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019632 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019633 }
19634 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019635 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019636}
19637
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019638sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019639{
19640 my ($Path, $LibVersion) = @_;
19641 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019642 my $Name = get_filename($Path);
19643 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019644 return 1;
19645 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019646 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19648 return 1;
19649 }
19650 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19651 {
19652 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19653 return 1;
19654 }
19655 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019656 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019658 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659 return 1;
19660 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019661 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019662 return 1;
19663 }
19664 }
19665 return 0;
19666}
19667
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019668sub specificHeader($$)
19669{
19670 my ($Header, $Spec) = @_;
19671 my $Name = get_filename($Header);
19672
19673 if($Spec eq "windows")
19674 {# MS Windows
19675 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19676 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19677 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19678 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19679 my @Dirs = (
19680 "win32",
19681 "win64",
19682 "win",
19683 "windows",
19684 "msvcrt"
19685 ); # /gsf-win32/
19686 if(my $DIRs = join("|", @Dirs)) {
19687 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19688 }
19689 }
19690 elsif($Spec eq "macos")
19691 { # Mac OS
19692 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19693 }
19694
19695 return 0;
19696}
19697
19698sub skipAlienHeader($)
19699{
19700 my $Path = $_[0];
19701 my $Name = get_filename($Path);
19702 my $Dir = get_dirname($Path);
19703
19704 if($Tolerance=~/2/)
19705 { # 2 - skip internal headers
19706 my @Terms = (
19707 "p",
19708 "priv",
19709 "int",
19710 "impl",
19711 "implementation",
19712 "internal",
19713 "private",
19714 "old",
19715 "compat",
19716 "debug",
19717 "test",
19718 "gen"
19719 );
19720
19721 my @Dirs = (
19722 "private",
19723 "priv",
19724 "port",
19725 "impl",
19726 "internal",
19727 "detail",
19728 "details",
19729 "old",
19730 "compat",
19731 "debug",
19732 "config",
19733 "compiler",
19734 "platform",
19735 "test"
19736 );
19737
19738 if(my $TERMs = join("|", @Terms)) {
19739 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19740 }
19741 if(my $DIRs = join("|", @Dirs)) {
19742 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19743 }
19744
19745 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19746 }
19747
19748 if($Tolerance=~/1/)
19749 { # 1 - skip non-Linux headers
19750 if($OSgroup ne "windows")
19751 {
19752 if(specificHeader($Path, "windows")) {
19753 return 1;
19754 }
19755 }
19756 if($OSgroup ne "macos")
19757 {
19758 if(specificHeader($Path, "macos")) {
19759 return 1;
19760 }
19761 }
19762 }
19763
19764 # valid
19765 return 0;
19766}
19767
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019768sub skipHeader($$)
19769{
19770 my ($Path, $LibVersion) = @_;
19771 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019772 if(defined $Cache{"skipHeader"}{$Path}) {
19773 return $Cache{"skipHeader"}{$Path};
19774 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019775 if(defined $Tolerance and $Tolerance=~/1|2/)
19776 { # --tolerant
19777 if(skipAlienHeader($Path)) {
19778 return ($Cache{"skipHeader"}{$Path} = 1);
19779 }
19780 }
19781 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19782 return 0;
19783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019784 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19785}
19786
19787sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019788{ # returns:
19789 # 1 - if header should NOT be included and checked
19790 # 2 - if header should NOT be included, but should be checked
19791 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019792 my $Name = get_filename($Path);
19793 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019794 return $Kind;
19795 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019796 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19797 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019798 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019799 if(index($Path, $D)!=-1)
19800 {
19801 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19802 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 }
19805 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019806 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19807 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019809 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19810 {
19811 if($Name=~/$P/) {
19812 return $Kind;
19813 }
19814 if($P=~/[\/\\]/ and $Path=~/$P/) {
19815 return $Kind;
19816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019817 }
19818 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019819
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019820 return 0;
19821}
19822
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019823sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019824{
19825 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019826 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019827 { # system directory
19828 return;
19829 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019830 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019831 { # already registered
19832 return;
19833 }
19834 foreach my $Path (find_libs($Dir,"",1))
19835 {
19836 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019837 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019838 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019839 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019840 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19841}
19842
19843sub registerObject($$)
19844{
19845 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019846
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019847 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019848 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019849 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019850 {
19851 if(my $SONAME = getSONAME($Path)) {
19852 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19853 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019854 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019855 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19856 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019857 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019858
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019859 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019860 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019861 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019862 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019863 if($ObjArch ne getArch_GCC($LibVersion))
19864 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19865 $CheckedArch{$LibVersion} = 1;
19866 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 +040019867 }
19868 }
19869 }
19870}
19871
19872sub getArch_Object($)
19873{
19874 my $Path = $_[0];
19875
19876 my %MachineType = (
19877 "14C" => "x86",
19878 "8664" => "x86_64",
19879 "1C0" => "arm",
19880 "200" => "ia64"
19881 );
19882
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019883 my %ArchName = (
19884 "s390:31-bit" => "s390",
19885 "s390:64-bit" => "s390x",
19886 "powerpc:common" => "ppc32",
19887 "powerpc:common64" => "ppc64",
19888 "i386:x86-64" => "x86_64",
19889 "mips:3000" => "mips",
19890 "sparc:v8plus" => "sparcv9"
19891 );
19892
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019893 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019894 {
19895 my $DumpbinCmd = get_CmdPath("dumpbin");
19896 if(not $DumpbinCmd) {
19897 exitStatus("Not_Found", "can't find \"dumpbin\"");
19898 }
19899
19900 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19901 my $Out = `$Cmd`;
19902
19903 if($Out=~/(\w+)\smachine/)
19904 {
19905 if(my $Type = $MachineType{uc($1)})
19906 {
19907 return $Type;
19908 }
19909 }
19910 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019911 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019912 {
19913 my $ObjdumpCmd = get_CmdPath("objdump");
19914 if(not $ObjdumpCmd) {
19915 exitStatus("Not_Found", "can't find \"objdump\"");
19916 }
19917
19918 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019919
19920 if($OSgroup eq "windows") {
19921 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19922 }
19923 else {
19924 $Cmd = "LANG=$LOCALE ".$Cmd;
19925 }
19926 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019927
19928 if($Out=~/architecture:\s+([\w\-\:]+)/)
19929 {
19930 my $Arch = $1;
19931 if($Arch=~s/\:(.+)//)
19932 {
19933 my $Suffix = $1;
19934
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019935 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019936 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019937 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019938 }
19939 }
19940
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019941 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019942 $Arch = "x86";
19943 }
19944
19945 if($Arch eq "x86-64") {
19946 $Arch = "x86_64";
19947 }
19948
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019949 if($Arch eq "ia64-elf64") {
19950 $Arch = "ia64";
19951 }
19952
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019953 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019954 }
19955 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019956 elsif($OStarget=~/macos/)
19957 {
19958 my $OtoolCmd = get_CmdPath("otool");
19959 if(not $OtoolCmd) {
19960 exitStatus("Not_Found", "can't find \"otool\"");
19961 }
19962
19963 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19964 my $Out = qx/$Cmd/;
19965
19966 if($Out=~/X86_64/i) {
19967 return "x86_64";
19968 }
19969 elsif($Out=~/X86/i) {
19970 return "x86";
19971 }
19972 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019973 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019974 {
19975 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019976 # TODO
19977 }
19978
19979 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019980}
19981
19982sub getSONAME($)
19983{
19984 my $Path = $_[0];
19985 return if(not $Path);
19986 if(defined $Cache{"getSONAME"}{$Path}) {
19987 return $Cache{"getSONAME"}{$Path};
19988 }
19989 my $ObjdumpCmd = get_CmdPath("objdump");
19990 if(not $ObjdumpCmd) {
19991 exitStatus("Not_Found", "can't find \"objdump\"");
19992 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019993 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019994 if($OSgroup eq "windows") {
19995 $SonameCmd .= " | find \"SONAME\"";
19996 }
19997 else {
19998 $SonameCmd .= " | grep SONAME";
19999 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020000 if(my $SonameInfo = `$SonameCmd`)
20001 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020002 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
20003 return ($Cache{"getSONAME"}{$Path} = $1);
20004 }
20005 }
20006 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020007}
20008
20009sub getSOPaths_Dest($$)
20010{
20011 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020012 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020013 return ();
20014 }
20015 if(-f $Dest)
20016 {
20017 if(not parse_libname($Dest, "name", $OStarget)) {
20018 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
20019 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020020 registerObject($Dest, $LibVersion);
20021 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020022 return ($Dest);
20023 }
20024 elsif(-d $Dest)
20025 {
20026 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020027 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020028 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020029 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
20030 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020031 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020032 { # all files and symlinks that match the name of a library
20033 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
20034 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020035 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020036 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020037 }
20038 }
20039 }
20040 else
20041 { # search for all files and symlinks
20042 foreach my $Path (find_libs($Dest,"",""))
20043 {
20044 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020045 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020046 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020047 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020048 }
20049 if($OSgroup eq "macos")
20050 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020051 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020052 {
20053 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020054 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020055 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020056 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
20057 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020058 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020059 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020060 }
20061 }
20062 }
20063 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020064 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 }
20066 else {
20067 return ();
20068 }
20069}
20070
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020071sub realpath_F($)
20072{
20073 my $Path = $_[0];
20074 return path_format(realpath($Path), $OSgroup);
20075}
20076
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020077sub isCyclical($$)
20078{
20079 my ($Stack, $Value) = @_;
20080 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020081}
20082
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020083sub getGCC_Opts($)
20084{ # to use in module
20085 my $LibVersion = $_[0];
20086
20087 my @Opts = ();
20088
20089 if($CompilerOptions{$LibVersion})
20090 { # user-defined options
20091 push(@Opts, $CompilerOptions{$LibVersion});
20092 }
20093 if($GccOptions)
20094 { # additional
20095 push(@Opts, $GccOptions);
20096 }
20097
20098 if(@Opts) {
20099 return join(" ", @Opts);
20100 }
20101
20102 return undef;
20103}
20104
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020105sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020106{
20107 my $LibVersion = $_[0];
20108
20109 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20110 return $Cache{"getArch_GCC"}{$LibVersion};
20111 }
20112
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020113 if(not $GCC_PATH) {
20114 return undef;
20115 }
20116
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020117 my $Arch = undef;
20118
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020119 if(my $Target = get_dumpmachine($GCC_PATH))
20120 {
20121 if($Target=~/x86_64/) {
20122 $Arch = "x86_64";
20123 }
20124 elsif($Target=~/i[3-6]86/) {
20125 $Arch = "x86";
20126 }
20127 elsif($Target=~/\Aarm/i) {
20128 $Arch = "arm";
20129 }
20130 }
20131
20132 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020133 {
20134 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20135
20136 my $Cmd = $GCC_PATH." test.c -o test";
20137 if(my $Opts = getGCC_Opts($LibVersion))
20138 { # user-defined options
20139 $Cmd .= " ".$Opts;
20140 }
20141
20142 chdir($TMP_DIR);
20143 system($Cmd);
20144 chdir($ORIG_DIR);
20145
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020146 my $EX = join_P($TMP_DIR, "test");
20147
20148 if($OSgroup eq "windows") {
20149 $EX = join_P($TMP_DIR, "test.exe");
20150 }
20151
20152 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020153
20154 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020155 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020156 }
20157
20158 if(not $Arch) {
20159 exitStatus("Error", "can't check ARCH type");
20160 }
20161
20162 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20163}
20164
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020165sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020166{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020167 my $LibVersion = $_[0];
20168
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020169 my $Size = undef;
20170
20171 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020172 if(my $Arch = getArch($LibVersion))
20173 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020174 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020175 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020176 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020177 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20178 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020179 }
20180 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020181
20182 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020183 {
20184 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020185
20186 my $Cmd = $GCC_PATH." -E -dD empty.h";
20187 if(my $Opts = getGCC_Opts($LibVersion))
20188 { # user-defined options
20189 $Cmd .= " ".$Opts;
20190 }
20191
20192 chdir($TMP_DIR);
20193 my $Defines = `$Cmd`;
20194 chdir($ORIG_DIR);
20195
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020196 unlink("$TMP_DIR/empty.h");
20197
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020198 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20199 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020200 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020201 }
20202 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20203 { # GCC 3
20204 my $PTRDIFF = $1;
20205 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020206 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020207 }
20208 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020209 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020210 }
20211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020212 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020213
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020214 if(not $Size) {
20215 exitStatus("Error", "can't check WORD size");
20216 }
20217
20218 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219}
20220
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020221sub getWordSize($)
20222{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020223 return $WORD_SIZE{$_[0]};
20224}
20225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020226sub majorVersion($)
20227{
20228 my $V = $_[0];
20229 return 0 if(not $V);
20230 my @VParts = split(/\./, $V);
20231 return $VParts[0];
20232}
20233
20234sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020235{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020236 my ($V1, $V2) = @_;
20237 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020238 my @V1Parts = split(/\./, $V1);
20239 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020240 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20241 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020242 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20243 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20244 }
20245 return -1 if($#V1Parts < $#V2Parts);
20246 return 1 if($#V1Parts > $#V2Parts);
20247 return 0;
20248}
20249
20250sub read_ABI_Dump($$)
20251{
20252 my ($LibVersion, $Path) = @_;
20253 return if(not $LibVersion or not -e $Path);
20254 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020255 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020256 { # input *.abi
20257 $FilePath = $Path;
20258 }
20259 else
20260 { # input *.abi.tar.gz
20261 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020262 if(not isDump_U($FilePath)) {
20263 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020265 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020266
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020268
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020269 my $Line = readLineNum($FilePath, 0);
20270 if($Line=~/xml/)
20271 { # XML format
20272 loadModule("XmlDump");
20273 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020274 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020275 else
20276 { # Perl Data::Dumper format (default)
20277 open(DUMP, $FilePath);
20278 local $/ = undef;
20279 my $Content = <DUMP>;
20280 close(DUMP);
20281
20282 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20283 { # remove temp file
20284 unlink($FilePath);
20285 }
20286 if($Content!~/};\s*\Z/) {
20287 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20288 }
20289 $ABI = eval($Content);
20290 if(not $ABI) {
20291 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020293 }
20294 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020295 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020296 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020297 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020298 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020299 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020300 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020301 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020302 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020303
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020304 if($ABI->{"PublicABI"}) {
20305 $UsedDump{$LibVersion}{"Public"} = 1;
20306 }
20307
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020308 if($ABI->{"ABI_DUMP_VERSION"})
20309 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020310 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020311 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020312 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020313 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020314 }
20315 else
20316 { # support for old ABI dumps
20317 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020318 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020319 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020320 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020321 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020322
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020323 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020324 {
20325 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 +040020326 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020327
20328 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20329 { # DWARF ABI Dump
20330 $UseConv_Real{$LibVersion}{"P"} = 1;
20331 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20332
20333 $UsedDump{$LibVersion}{"DWARF"} = 1;
20334
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020335 if(not $TargetComponent_Opt)
20336 {
20337 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20338 $TargetComponent = "module";
20339 }
20340 else {
20341 $TargetComponent = "object";
20342 }
20343 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020344 }
20345
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020346 if(not checkDump($LibVersion, "2.11"))
20347 { # old ABI dumps
20348 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020349 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020350 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020351 { # ABI dump created with --binary option
20352 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20353 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020354 else
20355 { # default
20356 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20357 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020358
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020359 if(defined $ABI->{"Mode"}
20360 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020361 { # --ext option
20362 $ExtendedCheck = 1;
20363 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020364 if($ABI->{"Extra"}) {
20365 $ExtraDump = 1;
20366 }
20367
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020368 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020369 {
20370 $UsedDump{$LibVersion}{"L"} = $Lang;
20371 setLanguage($LibVersion, $Lang);
20372 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020373 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020374 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020375 }
20376 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020377 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020378 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020379 if(not $TInfo)
20380 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020381 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020382 }
20383 my %Tid_TDid = ();
20384 foreach my $TDid (keys(%{$TInfo}))
20385 {
20386 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20387 {
20388 $MAX_ID = $Tid if($Tid>$MAX_ID);
20389 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020390 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020391 }
20392 }
20393 my %NewID = ();
20394 foreach my $Tid (keys(%Tid_TDid))
20395 {
20396 my @TDids = keys(%{$Tid_TDid{$Tid}});
20397 if($#TDids>=1)
20398 {
20399 foreach my $TDid (@TDids)
20400 {
20401 if($TDid) {
20402 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20403 }
20404 else
20405 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020406 my $ID = ++$MAX_ID;
20407
20408 $NewID{$TDid}{$Tid} = $ID;
20409 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20410 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020411 }
20412 }
20413 }
20414 else
20415 {
20416 my $TDid = $TDids[0];
20417 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20418 }
20419 }
20420 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20421 {
20422 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20423 if(defined $Info{"BaseType"})
20424 {
20425 my $Bid = $Info{"BaseType"}{"Tid"};
20426 my $BDid = $Info{"BaseType"}{"TDid"};
20427 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020428 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020429 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20430 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020432 }
20433 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020435 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020436 read_Machine_DumpInfo($ABI, $LibVersion);
20437 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020438 if(not $SymbolInfo{$LibVersion})
20439 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020440 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020441 }
20442 if(not keys(%{$SymbolInfo{$LibVersion}}))
20443 { # validation of old-version dumps
20444 if(not $ExtendedCheck) {
20445 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20446 }
20447 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020448 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020449 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020451 else
20452 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020453 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020454 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020455 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020456 }
20457 if(not $DepSymbols)
20458 { # Cannot reconstruct DepSymbols. This may result in false
20459 # positives if the old dump is for library 2. Not a problem if
20460 # old dumps are only from old libraries.
20461 $DepSymbols = {};
20462 }
20463 foreach my $Symbol (keys(%{$DepSymbols})) {
20464 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020467 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020468
20469 if(my $V = $TargetVersion{$LibVersion}) {
20470 $Descriptor{$LibVersion}{"Version"} = $V;
20471 }
20472 else {
20473 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20474 }
20475
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020476 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020477 { # if not defined by -skip-types option
20478 if(defined $ABI->{"SkipTypes"})
20479 {
20480 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20481 {
20482 $SkipTypes{$LibVersion}{$TName} = 1;
20483 }
20484 }
20485 if(defined $ABI->{"OpaqueTypes"})
20486 { # support for old dumps
20487 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20488 {
20489 $SkipTypes{$LibVersion}{$TName} = 1;
20490 }
20491 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020492 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020493
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020494 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020495 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020496 if(defined $ABI->{"SkipSymbols"}) {
20497 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20498 }
20499 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020500 { # support for old dumps
20501 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20502 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020503 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020504 { # support for old dumps
20505 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020507 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020508 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020509
20510 if(not $TargetHeaders{$LibVersion})
20511 { # if not defined by -headers-list option
20512 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20513 }
20514
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020515 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020516 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020517 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020519 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020520 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020521 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020522
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020523 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020524 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020525
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020526 if(not checkDump($LibVersion, "2.10.1")
20527 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020528 { # support for old ABI dumps: added target headers
20529 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020530 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020531 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020532
20533 if(not $ABI->{"PublicABI"})
20534 {
20535 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20536 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20537 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020539 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020540 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020541 if(defined $ABI->{"GccConstants"})
20542 { # 3.0
20543 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20544 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20545 }
20546 }
20547
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020548 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 if(not $NestedNameSpaces{$LibVersion})
20550 { # support for old dumps
20551 # Cannot reconstruct NameSpaces. This may affect design
20552 # of the compatibility report.
20553 $NestedNameSpaces{$LibVersion} = {};
20554 }
20555 # target system type
20556 # needed to adopt HTML report
20557 if(not $DumpSystem)
20558 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020559 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020560 }
20561 # recreate environment
20562 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20563 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020564 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020565 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020566 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20567 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020568 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020569 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020570 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020571 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20572 {
20573 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20574 setLanguage($LibVersion, "C++");
20575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020576 }
20577 }
20578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020579 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20580 {
20581 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20582 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20583 }
20584 }
20585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020587 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020588 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020589 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020590 {
20591 if(not $Symbol_Library{$LibVersion}{$MnglName}
20592 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20593 push(@VFunc, $MnglName);
20594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020595 }
20596 }
20597 translateSymbols(@VFunc, $LibVersion);
20598 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020599 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20600
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020601 if(not checkDump($LibVersion, "3.0"))
20602 { # support for old ABI dumps
20603 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20604 {
20605 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20606 {
20607 if(ref($BaseType) eq "HASH") {
20608 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20609 }
20610 }
20611 }
20612 }
20613
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020614 if(not checkDump($LibVersion, "3.2"))
20615 { # support for old ABI dumps
20616 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20617 {
20618 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20619 {
20620 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20621 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20622 }
20623 }
20624 }
20625
20626 # repair target headers list
20627 delete($TargetHeaders{$LibVersion});
20628 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020629 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20630 }
20631 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20632 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020633 }
20634
20635 # non-target constants from anon enums
20636 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20637 {
20638 if(not $ExtraDump
20639 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20640 {
20641 delete($Constants{$LibVersion}{$Name});
20642 }
20643 }
20644 }
20645
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020646 if(not checkDump($LibVersion, "2.20"))
20647 { # support for old ABI dumps
20648 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20649 {
20650 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20651
20652 if($TType=~/Struct|Union|Enum|Typedef/)
20653 { # repair complex types first
20654 next;
20655 }
20656
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020657 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020658 {
20659 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20660 if($BType=~/Struct|Union|Enum/i)
20661 {
20662 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20663 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20664 }
20665 }
20666 }
20667 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20668 {
20669 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20670 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20671 if($TType=~/Struct|Union|Enum/) {
20672 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20673 }
20674 }
20675 }
20676
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020677 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020678 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020679 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20680 { # support for old ABI dumps < 2.0 (ACC 1.22)
20681 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20682 {
20683 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20684 {
20685 if($Access ne "public") {
20686 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20687 }
20688 }
20689 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20690 }
20691 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20692 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020693 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20694 { # support for old ABI dumps
20695 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20696 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020697 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20698 { # DWARF ABI Dumps
20699 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20700 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020701 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20702 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20703 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020704
20705 # support for old formatting of type names
20706 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20707
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020708 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20709 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020710 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020711 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20712 {
20713 if($SubId eq $TypeId)
20714 { # Fix erroneus ABI dump
20715 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20716 next;
20717 }
20718
20719 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020721 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020722 if($TInfo{"Type"} eq "MethodPtr")
20723 {
20724 if(defined $TInfo{"Param"})
20725 { # support for old ABI dumps <= 1.17
20726 if(not defined $TInfo{"Param"}{"0"})
20727 {
20728 my $Max = keys(%{$TInfo{"Param"}});
20729 foreach my $Pos (1 .. $Max) {
20730 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20731 }
20732 delete($TInfo{"Param"}{$Max});
20733 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20734 }
20735 }
20736 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020737 if($TInfo{"BaseType"} eq $TypeId)
20738 { # fix ABI dump
20739 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20740 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020741
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020742 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020743 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020744 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020746 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20747 if(not $BName)
20748 { # broken type
20749 next;
20750 }
20751 if($TInfo{"Name"} eq $BName)
20752 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020753 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020754 next;
20755 }
20756 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20757 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 }
20759 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020760 }
20761 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20762 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020763 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020764 }
20765 }
20766
20767 if(not checkDump($LibVersion, "2.15"))
20768 { # support for old ABI dumps
20769 my %Dups = ();
20770 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20771 {
20772 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020773 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020774 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20775 { # remove template decls
20776 delete($SymbolInfo{$LibVersion}{$InfoId});
20777 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020779 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020780 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20781 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020782 { # templates
20783 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020784 }
20785 }
20786 }
20787
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020788 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20789 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020790 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20791 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20792 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20793 { # support for old ABI dumps (< 3.1)
20794 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20795 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20796 { # add "this" first parameter
20797 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20798 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20799
20800 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20801 {
20802 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20803 foreach my $Pos (reverse(0 .. $#Pos)) {
20804 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20805 }
20806 }
20807 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20808 }
20809 }
20810
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020811 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20812 { # ABI dumps have no mangled names for C-functions
20813 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20814 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020815 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20816 { # support for old ABI dumps
20817 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20818 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020819 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20820 { # DWARF ABI Dumps
20821 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20822 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020823 }
20824
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020825 $Descriptor{$LibVersion}{"Dump"} = 1;
20826}
20827
20828sub read_Machine_DumpInfo($$)
20829{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020830 my ($ABI, $LibVersion) = @_;
20831 if($ABI->{"Arch"}) {
20832 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020833 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020834 if($ABI->{"WordSize"}) {
20835 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020836 }
20837 else
20838 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020839 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020840 }
20841 if(not $WORD_SIZE{$LibVersion})
20842 { # support for old dumps (<1.23)
20843 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20844 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020845 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020846 }
20847 else
20848 {
20849 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020850 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020851 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020852 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20853 { # any "pointer"-type
20854 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020855 last;
20856 }
20857 }
20858 if($PSize)
20859 { # a pointer type size
20860 $WORD_SIZE{$LibVersion} = $PSize;
20861 }
20862 else {
20863 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20864 }
20865 }
20866 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020867 if($ABI->{"GccVersion"}) {
20868 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020869 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030020870 elsif($ABI->{"ClangVersion"}) {
20871 $CLANG_VERSION{$LibVersion} = $ABI->{"ClangVersion"};
20872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020873}
20874
20875sub read_Libs_DumpInfo($$)
20876{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020877 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020878 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20879 if(not $Library_Symbol{$LibVersion})
20880 { # support for old dumps
20881 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 if(keys(%{$Library_Symbol{$LibVersion}})
20884 and not $DumpAPI) {
20885 $Descriptor{$LibVersion}{"Libs"} = "OK";
20886 }
20887}
20888
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020889sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020890{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020891 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020892
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020893 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894 and not $DumpAPI) {
20895 $Descriptor{$LibVersion}{"Headers"} = "OK";
20896 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020897 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020898 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020899 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020900 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020901 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020902
20903 if(keys(%{$ABI->{"Sources"}})
20904 and not $DumpAPI) {
20905 $Descriptor{$LibVersion}{"Sources"} = "OK";
20906 }
20907 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020908 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020909 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20910 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020912}
20913
20914sub find_libs($$$)
20915{
20916 my ($Path, $Type, $MaxDepth) = @_;
20917 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020918 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020919}
20920
20921sub createDescriptor($$)
20922{
20923 my ($LibVersion, $Path) = @_;
20924 if(not $LibVersion or not $Path
20925 or not -e $Path) {
20926 return "";
20927 }
20928 if(-d $Path)
20929 { # directory with headers files and shared objects
20930 return "
20931 <version>
20932 ".$TargetVersion{$LibVersion}."
20933 </version>
20934
20935 <headers>
20936 $Path
20937 </headers>
20938
20939 <libs>
20940 $Path
20941 </libs>";
20942 }
20943 else
20944 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020945 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020946 { # standard XML-descriptor
20947 return readFile($Path);
20948 }
20949 elsif(is_header($Path, 2, $LibVersion))
20950 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020951 $CheckHeadersOnly = 1;
20952
20953 if($LibVersion==1) {
20954 $TargetVersion{$LibVersion} = "X";
20955 }
20956
20957 if($LibVersion==2) {
20958 $TargetVersion{$LibVersion} = "Y";
20959 }
20960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961 return "
20962 <version>
20963 ".$TargetVersion{$LibVersion}."
20964 </version>
20965
20966 <headers>
20967 $Path
20968 </headers>
20969
20970 <libs>
20971 none
20972 </libs>";
20973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020974 else
20975 { # standard XML-descriptor
20976 return readFile($Path);
20977 }
20978 }
20979}
20980
20981sub detect_lib_default_paths()
20982{
20983 my %LPaths = ();
20984 if($OSgroup eq "bsd")
20985 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020986 if(my $LdConfig = get_CmdPath("ldconfig"))
20987 {
20988 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20989 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020990 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20991 {
20992 my $Name = "lib".$1;
20993 if(not defined $LPaths{$Name}) {
20994 $LPaths{$Name} = $2;
20995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996 }
20997 }
20998 }
20999 else {
21000 printMsg("WARNING", "can't find ldconfig");
21001 }
21002 }
21003 else
21004 {
21005 if(my $LdConfig = get_CmdPath("ldconfig"))
21006 {
21007 if($SystemRoot and $OSgroup eq "linux")
21008 { # use host (x86) ldconfig with the target (arm) ld.so.conf
21009 if(-e $SystemRoot."/etc/ld.so.conf") {
21010 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
21011 }
21012 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021013 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
21014 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021015 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
21016 {
21017 my ($Name, $Path) = ($1, $2);
21018 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021019 if(not defined $LPaths{$Name})
21020 { # get first element from the list of available paths
21021
21022 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
21023 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
21024 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
21025
21026 $LPaths{$Name} = $Path;
21027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028 }
21029 }
21030 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040021031 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021032 printMsg("WARNING", "can't find ldconfig");
21033 }
21034 }
21035 return \%LPaths;
21036}
21037
21038sub detect_bin_default_paths()
21039{
21040 my $EnvPaths = $ENV{"PATH"};
21041 if($OSgroup eq "beos") {
21042 $EnvPaths.=":".$ENV{"BETOOLS"};
21043 }
21044 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021045 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021046 {
21047 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 next if(not $Path);
21049 if($SystemRoot
21050 and $Path=~/\A\Q$SystemRoot\E\//)
21051 { # do NOT use binaries from target system
21052 next;
21053 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021054 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021055 }
21056}
21057
21058sub detect_inc_default_paths()
21059{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021060 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021061 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021062 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021063 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021064 next if(index($Line, "/cc1plus ")!=-1);
21065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021066 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
21067 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021068 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021069 if(index($Path, "c++")!=-1
21070 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021071 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021072 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021073 if(not defined $MAIN_CPP_DIR
21074 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
21075 $MAIN_CPP_DIR = $Path;
21076 }
21077 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021078 elsif(index($Path, "gcc")!=-1) {
21079 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021080 }
21081 else
21082 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021083 if($Path=~/local[\/\\]+include/)
21084 { # local paths
21085 next;
21086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021087 if($SystemRoot
21088 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
21089 { # The GCC include path for user headers is not a part of the system root
21090 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
21091 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
21092 next;
21093 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021094 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021095 }
21096 }
21097 }
21098 unlink("$TMP_DIR/empty.h");
21099 return %DPaths;
21100}
21101
21102sub detect_default_paths($)
21103{
21104 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
21105 my $Search = $_[0];
21106 if($Search!~/inc/) {
21107 $HSearch = 0;
21108 }
21109 if($Search!~/lib/) {
21110 $LSearch = 0;
21111 }
21112 if($Search!~/bin/) {
21113 $BSearch = 0;
21114 }
21115 if($Search!~/gcc/) {
21116 $GSearch = 0;
21117 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021118 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021119 { # <search_headers> section of the XML descriptor
21120 # do NOT search for systems headers
21121 $HSearch = 0;
21122 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021123 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021124 { # <search_libs> section of the XML descriptor
21125 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021126 $LSearch = 0;
21127 }
21128 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21129 { # additional search paths
21130 next if($Type eq "include" and not $HSearch);
21131 next if($Type eq "lib" and not $LSearch);
21132 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021133 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021134 }
21135 if($OSgroup ne "windows")
21136 { # unix-like
21137 foreach my $Type ("include", "lib", "bin")
21138 { # automatic detection of system "devel" directories
21139 next if($Type eq "include" and not $HSearch);
21140 next if($Type eq "lib" and not $LSearch);
21141 next if($Type eq "bin" and not $BSearch);
21142 my ($UsrDir, $RootDir) = ("/usr", "/");
21143 if($SystemRoot and $Type ne "bin")
21144 { # 1. search for target headers and libraries
21145 # 2. use host commands: ldconfig, readelf, etc.
21146 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21147 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021148 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021149 if(-d $RootDir."/".$Type)
21150 { # if "/lib" is symbolic link
21151 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021152 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021153 }
21154 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021155 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021156 }
21157 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021158 if(-d $UsrDir)
21159 {
21160 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161 if(-d $UsrDir."/".$Type)
21162 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021163 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164 }
21165 }
21166 }
21167 }
21168 if($BSearch)
21169 {
21170 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021171 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021172 }
21173 # check environment variables
21174 if($OSgroup eq "beos")
21175 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021176 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021177 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021178 if($_ eq ".") {
21179 next;
21180 }
21181 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21182 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21183 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021184 }
21185 }
21186 if($HSearch)
21187 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021188 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21189 split(/:|;/, $ENV{"BEINCLUDES"})
21190 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021191 }
21192 if($LSearch)
21193 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021194 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21195 split(/:|;/, $ENV{"BELIBRARIES"}),
21196 split(/:|;/, $ENV{"LIBRARY_PATH"})
21197 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 }
21199 }
21200 if($LSearch)
21201 { # using linker to get system paths
21202 if(my $LPaths = detect_lib_default_paths())
21203 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021204 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021205 foreach my $Name (keys(%{$LPaths}))
21206 {
21207 if($SystemRoot
21208 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21209 { # wrong ldconfig configuration
21210 # check your <sysroot>/etc/ld.so.conf
21211 next;
21212 }
21213 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021214 if(my $Dir = get_dirname($LPaths->{$Name})) {
21215 $Dirs{$Dir} = 1;
21216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021218 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021219 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021220 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021221 }
21222 if($BSearch)
21223 {
21224 if($CrossGcc)
21225 { # --cross-gcc=arm-linux-gcc
21226 if(-e $CrossGcc)
21227 { # absolute or relative path
21228 $GCC_PATH = get_abs_path($CrossGcc);
21229 }
21230 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21231 { # command name
21232 $GCC_PATH = $CrossGcc;
21233 }
21234 else {
21235 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21236 }
21237 if($GCC_PATH=~/\s/) {
21238 $GCC_PATH = "\"".$GCC_PATH."\"";
21239 }
21240 }
21241 }
21242 if($GSearch)
21243 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021244 if(not $CrossGcc)
21245 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021246 $GCC_PATH = get_CmdPath("gcc");
21247 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021248 if(not $GCC_PATH)
21249 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021250 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021251 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021252 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021253 { # select the latest version
21254 @GCCs = sort {$b cmp $a} @GCCs;
21255 if(check_gcc($GCCs[0], "3"))
21256 {
21257 $GCC_PATH = $GCCs[0];
21258 last;
21259 }
21260 }
21261 }
21262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263 if(not $GCC_PATH) {
21264 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21265 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021266
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021267 my $GCC_Ver = get_dumpversion($GCC_PATH);
21268 if($GCC_Ver eq "4.8")
21269 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21270 my $Info = `$GCC_PATH --version`;
21271
21272 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21273 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21274 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21275 $GCC_Ver = $2;
21276 }
21277 }
21278
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021279 if($OStarget=~/macos/)
21280 {
21281 my $Info = `$GCC_PATH --version`;
21282
21283 if($Info=~/clang/i) {
21284 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21285 }
21286 }
21287
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021288 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021289 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021290 my $GccTarget = get_dumpmachine($GCC_PATH);
21291
21292 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021293 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021294 $OStarget = "linux";
21295 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021296 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021297 elsif($GccTarget=~/symbian/)
21298 {
21299 $OStarget = "symbian";
21300 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21301 }
21302
21303 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21304
21305 # check GCC version
21306 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21307 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021308 # introduced in 4.8 and fixed in 4.8.3
21309 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.");
21310
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021311 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021312 }
21313 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021314 else {
21315 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021316 }
21317 }
21318 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021319 {
21320 # GCC standard paths
21321 if($GCC_PATH and not $NoStdInc)
21322 {
21323 my %DPaths = detect_inc_default_paths();
21324 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21325 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21326 @DefaultIncPaths = @{$DPaths{"Inc"}};
21327 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21328 }
21329
21330 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021331 my $IncPath = "/usr/include";
21332 if($SystemRoot) {
21333 $IncPath = $SystemRoot.$IncPath;
21334 }
21335 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021336 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021337 }
21338 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021339
21340 if($ExtraInfo)
21341 {
21342 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21343 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021345}
21346
21347sub getLIB_EXT($)
21348{
21349 my $Target = $_[0];
21350 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21351 return $Ext;
21352 }
21353 return $OS_LibExt{$LIB_TYPE}{"default"};
21354}
21355
21356sub getAR_EXT($)
21357{
21358 my $Target = $_[0];
21359 if(my $Ext = $OS_Archive{$Target}) {
21360 return $Ext;
21361 }
21362 return $OS_Archive{"default"};
21363}
21364
21365sub get_dumpversion($)
21366{
21367 my $Cmd = $_[0];
21368 return "" if(not $Cmd);
21369 if($Cache{"get_dumpversion"}{$Cmd}) {
21370 return $Cache{"get_dumpversion"}{$Cmd};
21371 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021372 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021373 chomp($V);
21374 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21375}
21376
21377sub get_dumpmachine($)
21378{
21379 my $Cmd = $_[0];
21380 return "" if(not $Cmd);
21381 if($Cache{"get_dumpmachine"}{$Cmd}) {
21382 return $Cache{"get_dumpmachine"}{$Cmd};
21383 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021384 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021385 chomp($Machine);
21386 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21387}
21388
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021389sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021390{
21391 my $Cmd = $_[0];
21392 return "" if(not $Cmd);
21393 my @Options = (
21394 "--version",
21395 "-help"
21396 );
21397 foreach my $Opt (@Options)
21398 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021399 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 if($Info) {
21401 return 1;
21402 }
21403 }
21404 return 0;
21405}
21406
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021407sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021408{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021409 my ($Cmd, $ReqVer) = @_;
21410 return 0 if(not $Cmd or not $ReqVer);
21411 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21412 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021413 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021414 if(my $GccVer = get_dumpversion($Cmd))
21415 {
21416 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21417 if(cmpVersions($GccVer, $ReqVer)>=0) {
21418 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21419 }
21420 }
21421 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021422}
21423
21424sub get_depth($)
21425{
21426 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021427 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 }
21429 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21430}
21431
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021432sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021433{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021434 return if($Cache{"registerGccHeaders"}); # this function should be called once
21435
21436 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021437 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021438 my @Headers = cmd_find($Path,"f");
21439 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21440 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021441 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021442 my $FileName = get_filename($HPath);
21443 if(not defined $DefaultGccHeader{$FileName})
21444 { # skip duplicated
21445 $DefaultGccHeader{$FileName} = $HPath;
21446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021447 }
21448 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021449 $Cache{"registerGccHeaders"} = 1;
21450}
21451
21452sub registerCppHeaders()
21453{
21454 return if($Cache{"registerCppHeaders"}); # this function should be called once
21455
21456 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021457 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021458 my @Headers = cmd_find($CppDir,"f");
21459 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21460 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021461 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021462 my $FileName = get_filename($Path);
21463 if(not defined $DefaultCppHeader{$FileName})
21464 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021465 $DefaultCppHeader{$FileName} = $Path;
21466 }
21467 }
21468 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021469 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021470}
21471
21472sub parse_libname($$$)
21473{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021474 return "" if(not $_[0]);
21475 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21476 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021477 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021478 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21479}
21480
21481sub parse_libname_I($$$)
21482{
21483 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021484
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 if($Target eq "symbian") {
21486 return parse_libname_symbian($Name, $Type);
21487 }
21488 elsif($Target eq "windows") {
21489 return parse_libname_windows($Name, $Type);
21490 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021491
21492 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021493 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021494 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021495 { # libSDL-1.2.so.0.7.1
21496 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021497 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021498 if($Type eq "name")
21499 { # libSDL-1.2
21500 # libwbxml2
21501 return $2;
21502 }
21503 elsif($Type eq "name+ext")
21504 { # libSDL-1.2.so
21505 # libwbxml2.so
21506 return $1;
21507 }
21508 elsif($Type eq "version")
21509 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021510 if(defined $7
21511 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021512 { # 0.7.1
21513 return $7;
21514 }
21515 else
21516 { # libc-2.5.so (=>2.5 version)
21517 my $MV = $5;
21518 $MV=~s/\A[\-\_]+//g;
21519 return $MV;
21520 }
21521 }
21522 elsif($Type eq "short")
21523 { # libSDL
21524 # libwbxml2
21525 return $3;
21526 }
21527 elsif($Type eq "shortest")
21528 { # SDL
21529 # wbxml
21530 return shortest_name($3);
21531 }
21532 }
21533 return "";# error
21534}
21535
21536sub parse_libname_symbian($$)
21537{
21538 my ($Name, $Type) = @_;
21539 my $Ext = getLIB_EXT("symbian");
21540 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21541 { # libpthread{00010001}.dso
21542 if($Type eq "name")
21543 { # libpthread{00010001}
21544 return $2;
21545 }
21546 elsif($Type eq "name+ext")
21547 { # libpthread{00010001}.dso
21548 return $1;
21549 }
21550 elsif($Type eq "version")
21551 { # 00010001
21552 my $V = $4;
21553 $V=~s/\{(.+)\}/$1/;
21554 return $V;
21555 }
21556 elsif($Type eq "short")
21557 { # libpthread
21558 return $3;
21559 }
21560 elsif($Type eq "shortest")
21561 { # pthread
21562 return shortest_name($3);
21563 }
21564 }
21565 return "";# error
21566}
21567
21568sub parse_libname_windows($$)
21569{
21570 my ($Name, $Type) = @_;
21571 my $Ext = getLIB_EXT("windows");
21572 if($Name=~/((.+?)\.$Ext)\Z/)
21573 { # netapi32.dll
21574 if($Type eq "name")
21575 { # netapi32
21576 return $2;
21577 }
21578 elsif($Type eq "name+ext")
21579 { # netapi32.dll
21580 return $1;
21581 }
21582 elsif($Type eq "version")
21583 { # DLL version embedded
21584 # at binary-level
21585 return "";
21586 }
21587 elsif($Type eq "short")
21588 { # netapi32
21589 return $2;
21590 }
21591 elsif($Type eq "shortest")
21592 { # netapi
21593 return shortest_name($2);
21594 }
21595 }
21596 return "";# error
21597}
21598
21599sub shortest_name($)
21600{
21601 my $Name = $_[0];
21602 # remove prefix
21603 $Name=~s/\A(lib|open)//;
21604 # remove suffix
21605 $Name=~s/[\W\d_]+\Z//i;
21606 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21607 return $Name;
21608}
21609
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021610sub createSymbolsList($$$$$)
21611{
21612 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021614 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021615 prepareSymbols(1);
21616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021617 my %SymbolHeaderLib = ();
21618 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021620 # Get List
21621 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21622 {
21623 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021624 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021625 next;
21626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021627 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021628 { # skip other symbols
21629 next;
21630 }
21631 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21632 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021633 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 next;
21635 }
21636 my $DyLib = $Symbol_Library{1}{$Symbol};
21637 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021638 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021639 next;
21640 }
21641 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21642 $Total+=1;
21643 }
21644 # Draw List
21645 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21646 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21647 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21648 {
21649 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21650 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021651 my %NS_Symbol = ();
21652 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021653 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021654 }
21655 foreach my $NameSpace (sort keys(%NS_Symbol))
21656 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021657 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021658 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21659 foreach my $Symbol (@SortedInterfaces)
21660 {
21661 my $SubReport = "";
21662 my $Signature = get_Signature($Symbol, 1);
21663 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021664 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021665 }
21666 if($Symbol=~/\A(_Z|\?)/)
21667 {
21668 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021669 $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 +040021670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021671 else {
21672 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21673 }
21674 }
21675 else
21676 {
21677 if($Signature) {
21678 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21679 }
21680 else {
21681 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21682 }
21683 }
21684 $SYMBOLS_LIST .= $SubReport;
21685 }
21686 }
21687 $SYMBOLS_LIST .= "<br/>\n";
21688 }
21689 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021690 # clear info
21691 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21692 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21693 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21694 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021695 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021696 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021697 my $CssStyles = readModule("Styles", "SymbolsList.css");
21698 my $JScripts = readModule("Scripts", "Sections.js");
21699 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021700 my $Title = "$LName: public symbols";
21701 my $Keywords = "$LName, API, symbols";
21702 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021703 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021704 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021705 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021706 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021707 writeFile($SaveTo, $SYMBOLS_LIST);
21708}
21709
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021710sub add_target_libs($)
21711{
21712 foreach (@{$_[0]}) {
21713 $TargetLibs{$_} = 1;
21714 }
21715}
21716
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021717sub is_target_lib($)
21718{
21719 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021720 if(not $LName) {
21721 return 0;
21722 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021723 if($OSgroup eq "windows") {
21724 $LName = lc($LName);
21725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021726 if($TargetLibraryName
21727 and $LName!~/\Q$TargetLibraryName\E/) {
21728 return 0;
21729 }
21730 if(keys(%TargetLibs)
21731 and not $TargetLibs{$LName}
21732 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21733 return 0;
21734 }
21735 return 1;
21736}
21737
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021738sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021739{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021740 my ($H, $V) = @_;
21741 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021742 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021743 if($TargetHeaders{$V}{$H}) {
21744 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021745 }
21746 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021747 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021748}
21749
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021750sub readLibs($)
21751{
21752 my $LibVersion = $_[0];
21753 if($OStarget eq "windows")
21754 { # dumpbin.exe will crash
21755 # without VS Environment
21756 check_win32_env();
21757 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021758 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021759 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021760 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021761}
21762
21763sub dump_sorting($)
21764{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021765 my $Hash = $_[0];
21766 return [] if(not $Hash);
21767 my @Keys = keys(%{$Hash});
21768 return [] if($#Keys<0);
21769 if($Keys[0]=~/\A\d+\Z/)
21770 { # numbers
21771 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021772 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021773 else
21774 { # strings
21775 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021776 }
21777}
21778
21779sub printMsg($$)
21780{
21781 my ($Type, $Msg) = @_;
21782 if($Type!~/\AINFO/) {
21783 $Msg = $Type.": ".$Msg;
21784 }
21785 if($Type!~/_C\Z/) {
21786 $Msg .= "\n";
21787 }
21788 if($Quiet)
21789 { # --quiet option
21790 appendFile($COMMON_LOG_PATH, $Msg);
21791 }
21792 else
21793 {
21794 if($Type eq "ERROR") {
21795 print STDERR $Msg;
21796 }
21797 else {
21798 print $Msg;
21799 }
21800 }
21801}
21802
21803sub exitStatus($$)
21804{
21805 my ($Code, $Msg) = @_;
21806 printMsg("ERROR", $Msg);
21807 exit($ERROR_CODE{$Code});
21808}
21809
21810sub exitReport()
21811{ # the tool has run without any errors
21812 printReport();
21813 if($COMPILE_ERRORS)
21814 { # errors in headers may add false positives/negatives
21815 exit($ERROR_CODE{"Compile_Error"});
21816 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021817 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21818 { # --binary
21819 exit($ERROR_CODE{"Incompatible"});
21820 }
21821 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21822 { # --source
21823 exit($ERROR_CODE{"Incompatible"});
21824 }
21825 elsif($RESULT{"Source"}{"Problems"}
21826 or $RESULT{"Binary"}{"Problems"})
21827 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021828 exit($ERROR_CODE{"Incompatible"});
21829 }
21830 else {
21831 exit($ERROR_CODE{"Compatible"});
21832 }
21833}
21834
21835sub readRules($)
21836{
21837 my $Kind = $_[0];
21838 if(not -f $RULES_PATH{$Kind}) {
21839 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21840 }
21841 my $Content = readFile($RULES_PATH{$Kind});
21842 while(my $Rule = parseTag(\$Content, "rule"))
21843 {
21844 my $RId = parseTag(\$Rule, "id");
21845 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21846 foreach my $Prop (@Properties) {
21847 if(my $Value = parseTag(\$Rule, lc($Prop)))
21848 {
21849 $Value=~s/\n[ ]*//;
21850 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21851 }
21852 }
21853 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21854 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21855 }
21856 else {
21857 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21858 }
21859 }
21860}
21861
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021862sub getReportPath($)
21863{
21864 my $Level = $_[0];
21865 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21866 if($Level eq "Binary")
21867 {
21868 if($BinaryReportPath)
21869 { # --bin-report-path
21870 return $BinaryReportPath;
21871 }
21872 elsif($OutputReportPath)
21873 { # --report-path
21874 return $OutputReportPath;
21875 }
21876 else
21877 { # default
21878 return $Dir."/abi_compat_report.$ReportFormat";
21879 }
21880 }
21881 elsif($Level eq "Source")
21882 {
21883 if($SourceReportPath)
21884 { # --src-report-path
21885 return $SourceReportPath;
21886 }
21887 elsif($OutputReportPath)
21888 { # --report-path
21889 return $OutputReportPath;
21890 }
21891 else
21892 { # default
21893 return $Dir."/src_compat_report.$ReportFormat";
21894 }
21895 }
21896 else
21897 {
21898 if($OutputReportPath)
21899 { # --report-path
21900 return $OutputReportPath;
21901 }
21902 else
21903 { # default
21904 return $Dir."/compat_report.$ReportFormat";
21905 }
21906 }
21907}
21908
21909sub printStatMsg($)
21910{
21911 my $Level = $_[0];
21912 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21913}
21914
21915sub listAffected($)
21916{
21917 my $Level = $_[0];
21918 my $List = "";
21919 foreach (keys(%{$TotalAffected{$Level}}))
21920 {
21921 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21922 { # skip "Low"-severity problems
21923 next;
21924 }
21925 $List .= "$_\n";
21926 }
21927 my $Dir = get_dirname(getReportPath($Level));
21928 if($Level eq "Binary") {
21929 writeFile($Dir."/abi_affected.txt", $List);
21930 }
21931 elsif($Level eq "Source") {
21932 writeFile($Dir."/src_affected.txt", $List);
21933 }
21934}
21935
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021936sub printReport()
21937{
21938 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021939 createReport();
21940 if($JoinReport or $DoubleReport)
21941 {
21942 if($RESULT{"Binary"}{"Problems"}
21943 or $RESULT{"Source"}{"Problems"}) {
21944 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021946 else {
21947 printMsg("INFO", "result: COMPATIBLE");
21948 }
21949 printStatMsg("Binary");
21950 printStatMsg("Source");
21951 if($ListAffected)
21952 { # --list-affected
21953 listAffected("Binary");
21954 listAffected("Source");
21955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021956 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021957 elsif($BinaryOnly)
21958 {
21959 if($RESULT{"Binary"}{"Problems"}) {
21960 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21961 }
21962 else {
21963 printMsg("INFO", "result: COMPATIBLE");
21964 }
21965 printStatMsg("Binary");
21966 if($ListAffected)
21967 { # --list-affected
21968 listAffected("Binary");
21969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021970 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021971 elsif($SourceOnly)
21972 {
21973 if($RESULT{"Source"}{"Problems"}) {
21974 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21975 }
21976 else {
21977 printMsg("INFO", "result: COMPATIBLE");
21978 }
21979 printStatMsg("Source");
21980 if($ListAffected)
21981 { # --list-affected
21982 listAffected("Source");
21983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021984 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021985 if($StdOut)
21986 {
21987 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021988 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021989 printMsg("INFO", "compatibility report has been generated to stdout");
21990 }
21991 else
21992 { # default
21993 printMsg("INFO", "compatibility reports have been generated to stdout");
21994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021995 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021996 else
21997 {
21998 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021999 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022000 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
22001 }
22002 elsif($DoubleReport)
22003 { # default
22004 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
22005 }
22006 elsif($BinaryOnly)
22007 { # --binary
22008 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
22009 }
22010 elsif($SourceOnly)
22011 { # --source
22012 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
22013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022014 }
22015}
22016
22017sub check_win32_env()
22018{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022019 if(not $ENV{"VCINSTALLDIR"}
22020 or not $ENV{"INCLUDE"}) {
22021 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022022 }
22023}
22024
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022025sub diffSets($$)
22026{
22027 my ($S1, $S2) = @_;
22028 my @SK1 = keys(%{$S1});
22029 my @SK2 = keys(%{$S2});
22030 if($#SK1!=$#SK2) {
22031 return 1;
22032 }
22033 foreach my $K1 (@SK1)
22034 {
22035 if(not defined $S2->{$K1}) {
22036 return 1;
22037 }
22038 }
22039 return 0;
22040}
22041
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022042sub defaultDumpPath($$)
22043{
22044 my ($N, $V) = @_;
22045 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
22046}
22047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022048sub create_ABI_Dump()
22049{
22050 if(not -e $DumpAPI) {
22051 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
22052 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022053
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022054 if(isDump($DumpAPI)) {
22055 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022057 else {
22058 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022059 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022060
22061 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022062 { # set to default: N
22063 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022064 }
22065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 initLogging(1);
22067 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022068
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022069 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022070 if($OutputDumpPath)
22071 { # user defined path
22072 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022073 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022074 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
22075
22076 if(not $Archive and not $StdOut)
22077 { # check archive utilities
22078 if($OSgroup eq "windows")
22079 { # using zip
22080 my $ZipCmd = get_CmdPath("zip");
22081 if(not $ZipCmd) {
22082 exitStatus("Not_Found", "can't find \"zip\"");
22083 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022084 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022085 else
22086 { # using tar and gzip
22087 my $TarCmd = get_CmdPath("tar");
22088 if(not $TarCmd) {
22089 exitStatus("Not_Found", "can't find \"tar\"");
22090 }
22091 my $GzipCmd = get_CmdPath("gzip");
22092 if(not $GzipCmd) {
22093 exitStatus("Not_Found", "can't find \"gzip\"");
22094 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022095 }
22096 }
22097
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022098 if(not $Descriptor{1}{"Dump"})
22099 {
22100 if(not $CheckHeadersOnly) {
22101 readLibs(1);
22102 }
22103 if($CheckHeadersOnly) {
22104 setLanguage(1, "C++");
22105 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022106 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022107 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022108 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022109 if(not $Descriptor{1}{"Dump"})
22110 {
22111 if($Descriptor{1}{"Headers"}) {
22112 readHeaders(1);
22113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022114 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022115 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022116 if(not keys(%{$SymbolInfo{1}}))
22117 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022118 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022119 {
22120 if($CheckHeadersOnly) {
22121 exitStatus("Empty_Set", "the set of public symbols is empty");
22122 }
22123 else {
22124 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22125 }
22126 }
22127 }
22128 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022129 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022130 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22131 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022132 if($ExtraDump)
22133 { # add unmangled names to the ABI dump
22134 my @Names = ();
22135 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22136 {
22137 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22138 push(@Names, $MnglName);
22139 }
22140 }
22141 translateSymbols(@Names, 1);
22142 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22143 {
22144 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22145 {
22146 if(my $Unmangled = $tr_name{$MnglName})
22147 {
22148 if($MnglName ne $Unmangled) {
22149 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22150 }
22151 }
22152 }
22153 }
22154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022155
22156 my %GccConstants = (); # built-in GCC constants
22157 foreach my $Name (keys(%{$Constants{1}}))
22158 {
22159 if(not defined $Constants{1}{$Name}{"Header"})
22160 {
22161 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22162 delete($Constants{1}{$Name});
22163 }
22164 }
22165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022166 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022167 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022168 "TypeInfo" => $TypeInfo{1},
22169 "SymbolInfo" => $SymbolInfo{1},
22170 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022171 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022172 "SymbolVersion" => $SymVer{1},
22173 "LibraryVersion" => $Descriptor{1}{"Version"},
22174 "LibraryName" => $TargetLibraryName,
22175 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022176 "SkipTypes" => $SkipTypes{1},
22177 "SkipSymbols" => $SkipSymbols{1},
22178 "SkipNameSpaces" => $SkipNameSpaces{1},
22179 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022180 "Headers" => \%HeadersInfo,
22181 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022182 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022183 "NameSpaces" => $NestedNameSpaces{1},
22184 "Target" => $OStarget,
22185 "Arch" => getArch(1),
22186 "WordSize" => $WORD_SIZE{1},
22187 "GccVersion" => get_dumpversion($GCC_PATH),
22188 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22189 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22190 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022191 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022192 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022193 }
22194 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022195 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022197 if($ExtendedCheck)
22198 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022199 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022200 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022201 if($BinaryOnly)
22202 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022203 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022204 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022205 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022206 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022207 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022208 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22209 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022210 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022211
22212 my $ABI_DUMP = "";
22213 if($UseXML)
22214 {
22215 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022216 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022217 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022218 else
22219 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022220 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022222 if($StdOut)
22223 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022224 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022225 printMsg("INFO", "ABI dump has been generated to stdout");
22226 return;
22227 }
22228 else
22229 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022230 my ($DDir, $DName) = separate_path($DumpPath);
22231 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022232 if(not $Archive) {
22233 $DPath = $DumpPath;
22234 }
22235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022236 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022237
22238 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022239 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022240 close(DUMP);
22241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022242 if(not -s $DPath) {
22243 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22244 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022245 if($Archive) {
22246 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022247 }
22248
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022249 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022250 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022251 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022252 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022253 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022254 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022255 # 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 +040022256 }
22257}
22258
22259sub quickEmptyReports()
22260{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022261 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022262 # NOTE: the dump contains the "LibraryVersion" attribute
22263 # if you change the version, then your dump will be different
22264 # OVERCOME: use -v1 and v2 options for comparing dumps
22265 # and don't change version in the XML descriptor (and dumps)
22266 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022267 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22268 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022269 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022270 my $FilePath1 = $Descriptor{1}{"Path"};
22271 my $FilePath2 = $Descriptor{2}{"Path"};
22272
22273 if(not isDump_U($FilePath1)) {
22274 $FilePath1 = unpackDump($FilePath1);
22275 }
22276
22277 if(not isDump_U($FilePath2)) {
22278 $FilePath2 = unpackDump($FilePath2);
22279 }
22280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022281 if($FilePath1 and $FilePath2)
22282 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022283 my $Line = readLineNum($FilePath1, 0);
22284 if($Line=~/xml/)
22285 { # XML format
22286 # is not supported yet
22287 return;
22288 }
22289
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022290 local $/ = undef;
22291
22292 open(DUMP1, $FilePath1);
22293 my $Content1 = <DUMP1>;
22294 close(DUMP1);
22295
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022296 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022297
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022298 if($FilePath1 eq $FilePath2) {
22299 $Eq = 1;
22300 }
22301
22302 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022303 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022304 open(DUMP2, $FilePath2);
22305 my $Content2 = <DUMP2>;
22306 close(DUMP2);
22307
22308 if($Content1 eq $Content2) {
22309 $Eq = 1;
22310 }
22311
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022312 # clean memory
22313 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022314 }
22315
22316 if($Eq)
22317 {
22318 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022320 my $ABIdump = eval($Content1);
22321
22322 # clean memory
22323 undef $Content1;
22324
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022325 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022326 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 +040022327 }
22328 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022329 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022330 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22331 }
22332 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022333 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022334 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22335 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022336 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022337
22338 foreach (keys(%{$Registered_Headers{1}})) {
22339 $TargetHeaders{1}{$_} = 1;
22340 }
22341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022342 read_Libs_DumpInfo($ABIdump, 1);
22343 read_Machine_DumpInfo($ABIdump, 1);
22344 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022345
22346 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22347 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22348
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022349 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22350 {
22351 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22352 {
22353 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22354 next;
22355 }
22356 }
22357
22358 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22359 if($Access ne "private")
22360 {
22361 $CheckedSymbols{"Binary"}{$S} = 1;
22362 $CheckedSymbols{"Source"}{$S} = 1;
22363 }
22364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022365
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022366 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22367 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022368
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030022369 if(not defined $Descriptor{1}{"Version"}) {
22370 $Descriptor{1}{"Version"} = "X";
22371 }
22372
22373 if(not defined $Descriptor{2}{"Version"}) {
22374 $Descriptor{2}{"Version"} = "Y";
22375 }
22376
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022377 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22378 {
22379 $UsedDump{1}{"DWARF"} = 1;
22380 $UsedDump{2}{"DWARF"} = 1;
22381
22382 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22383 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22384 }
22385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022386 exitReport();
22387 }
22388 }
22389 }
22390}
22391
22392sub initLogging($)
22393{
22394 my $LibVersion = $_[0];
22395 # create log directory
22396 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22397 if($OutputLogPath{$LibVersion})
22398 { # user-defined by -log-path option
22399 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22400 }
22401 if($LogMode ne "n") {
22402 mkpath($LOG_DIR);
22403 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022404 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022405 if($Debug)
22406 { # debug directory
22407 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022408
22409 if(not $ExtraInfo)
22410 { # enable --extra-info
22411 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022413 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022414 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022415}
22416
22417sub writeLog($$)
22418{
22419 my ($LibVersion, $Msg) = @_;
22420 if($LogMode ne "n") {
22421 appendFile($LOG_PATH{$LibVersion}, $Msg);
22422 }
22423}
22424
22425sub resetLogging($)
22426{
22427 my $LibVersion = $_[0];
22428 if($LogMode!~/a|n/)
22429 { # remove old log
22430 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022431 if($Debug) {
22432 rmtree($DEBUG_PATH{$LibVersion});
22433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022434 }
22435}
22436
22437sub printErrorLog($)
22438{
22439 my $LibVersion = $_[0];
22440 if($LogMode ne "n") {
22441 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22442 }
22443}
22444
22445sub isDump($)
22446{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022447 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22448 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022449 return $1;
22450 }
22451 return 0;
22452}
22453
22454sub isDump_U($)
22455{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022456 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022457 return $1;
22458 }
22459 return 0;
22460}
22461
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022462sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022463{
22464 # read input XML descriptors or ABI dumps
22465 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022466 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022467 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022468 if(not -e $Descriptor{1}{"Path"}) {
22469 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022470 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022471
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022472 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022473 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022474 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022475 if(not -e $Descriptor{2}{"Path"}) {
22476 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022477 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022478
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022479 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022480
22481 if(not defined $DisableQuickEmptyReport)
22482 {
22483 if(isDump($Descriptor{1}{"Path"})
22484 and isDump($Descriptor{2}{"Path"}))
22485 { # optimization: equal ABI dumps
22486 quickEmptyReports();
22487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022488 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022490 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022491
22492 if(isDump($Descriptor{1}{"Path"})) {
22493 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022494 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022495 else {
22496 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22497 }
22498
22499 if(isDump($Descriptor{2}{"Path"})) {
22500 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22501 }
22502 else {
22503 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022504 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022505
22506 if(not $Descriptor{1}{"Version"})
22507 { # set to default: X
22508 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022509 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022510 }
22511
22512 if(not $Descriptor{2}{"Version"})
22513 { # set to default: Y
22514 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022515 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022516 }
22517
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022518 if(not $UsedDump{1}{"V"}) {
22519 initLogging(1);
22520 }
22521
22522 if(not $UsedDump{2}{"V"}) {
22523 initLogging(2);
22524 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022525
22526 # check input data
22527 if(not $Descriptor{1}{"Headers"}) {
22528 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022529 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022530 if(not $Descriptor{2}{"Headers"}) {
22531 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022532 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022533
22534 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022535 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022536 if(not $Descriptor{1}{"Libs"}) {
22537 exitStatus("Error", "can't find libraries info in descriptor d1");
22538 }
22539 if(not $Descriptor{2}{"Libs"}) {
22540 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022541 }
22542 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022543
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022544 if($UseDumps)
22545 { # --use-dumps
22546 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022547 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22548 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022549
22550 unlink($DumpPath1);
22551 unlink($DumpPath2);
22552
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022553 my $pid = fork();
22554 if($pid)
22555 { # dump on two CPU cores
22556 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22557 if($RelativeDirectory{1}) {
22558 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22559 }
22560 if($OutputLogPath{1}) {
22561 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22562 }
22563 if($CrossGcc) {
22564 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22565 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022566 if($Quiet)
22567 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022568 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022569 @PARAMS = (@PARAMS, "-logging-mode", "a");
22570 }
22571 elsif($LogMode and $LogMode ne "w")
22572 { # "w" is default
22573 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022574 }
22575 if($ExtendedCheck) {
22576 @PARAMS = (@PARAMS, "-extended");
22577 }
22578 if($UserLang) {
22579 @PARAMS = (@PARAMS, "-lang", $UserLang);
22580 }
22581 if($TargetVersion{1}) {
22582 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22583 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022584 if($BinaryOnly) {
22585 @PARAMS = (@PARAMS, "-binary");
22586 }
22587 if($SourceOnly) {
22588 @PARAMS = (@PARAMS, "-source");
22589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022590 if($SortDump) {
22591 @PARAMS = (@PARAMS, "-sort");
22592 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022593 if($DumpFormat and $DumpFormat ne "perl") {
22594 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22595 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022596 if($CheckHeadersOnly) {
22597 @PARAMS = (@PARAMS, "-headers-only");
22598 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022599 if($Debug)
22600 {
22601 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022602 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022604 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022605 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022606 exit(1);
22607 }
22608 }
22609 else
22610 { # child
22611 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22612 if($RelativeDirectory{2}) {
22613 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22614 }
22615 if($OutputLogPath{2}) {
22616 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22617 }
22618 if($CrossGcc) {
22619 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22620 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022621 if($Quiet)
22622 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022623 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022624 @PARAMS = (@PARAMS, "-logging-mode", "a");
22625 }
22626 elsif($LogMode and $LogMode ne "w")
22627 { # "w" is default
22628 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022629 }
22630 if($ExtendedCheck) {
22631 @PARAMS = (@PARAMS, "-extended");
22632 }
22633 if($UserLang) {
22634 @PARAMS = (@PARAMS, "-lang", $UserLang);
22635 }
22636 if($TargetVersion{2}) {
22637 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22638 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022639 if($BinaryOnly) {
22640 @PARAMS = (@PARAMS, "-binary");
22641 }
22642 if($SourceOnly) {
22643 @PARAMS = (@PARAMS, "-source");
22644 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022645 if($SortDump) {
22646 @PARAMS = (@PARAMS, "-sort");
22647 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022648 if($DumpFormat and $DumpFormat ne "perl") {
22649 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22650 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022651 if($CheckHeadersOnly) {
22652 @PARAMS = (@PARAMS, "-headers-only");
22653 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022654 if($Debug)
22655 {
22656 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022657 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022659 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022660 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022661 exit(1);
22662 }
22663 else {
22664 exit(0);
22665 }
22666 }
22667 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022668
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022669 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022670 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22671 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022672 if($TargetTitle ne $TargetLibraryName) {
22673 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022674 }
22675 if($ShowRetVal) {
22676 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22677 }
22678 if($CrossGcc) {
22679 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22680 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022681 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22682 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022683 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022684 }
22685 if($ReportFormat and $ReportFormat ne "html")
22686 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022687 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22688 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022689 if($OutputReportPath) {
22690 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22691 }
22692 if($BinaryReportPath) {
22693 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22694 }
22695 if($SourceReportPath) {
22696 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22697 }
22698 if($LoggingPath) {
22699 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22700 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022701 if($CheckHeadersOnly) {
22702 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22703 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022704 if($BinaryOnly) {
22705 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22706 }
22707 if($SourceOnly) {
22708 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22709 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022710 if($Debug)
22711 {
22712 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22713 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022715 system("perl", $0, @CMP_PARAMS);
22716 exit($?>>8);
22717 }
22718 if(not $Descriptor{1}{"Dump"}
22719 or not $Descriptor{2}{"Dump"})
22720 { # need GCC toolchain to analyze
22721 # header files and libraries
22722 detect_default_paths("inc|lib|gcc");
22723 }
22724 if(not $Descriptor{1}{"Dump"})
22725 {
22726 if(not $CheckHeadersOnly) {
22727 readLibs(1);
22728 }
22729 if($CheckHeadersOnly) {
22730 setLanguage(1, "C++");
22731 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022732 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022733 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022734 }
22735 if(not $Descriptor{2}{"Dump"})
22736 {
22737 if(not $CheckHeadersOnly) {
22738 readLibs(2);
22739 }
22740 if($CheckHeadersOnly) {
22741 setLanguage(2, "C++");
22742 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022743 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022744 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022745 }
22746 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22747 { # support for old ABI dumps
22748 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022749 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022750 {
22751 $WORD_SIZE{1} = $WORD_SIZE{2};
22752 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022754 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022755 {
22756 $WORD_SIZE{2} = $WORD_SIZE{1};
22757 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22758 }
22759 }
22760 elsif(not $WORD_SIZE{1}
22761 and not $WORD_SIZE{2})
22762 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022763 $WORD_SIZE{1} = "4";
22764 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022765 }
22766 if($Descriptor{1}{"Dump"})
22767 { # support for old ABI dumps
22768 prepareTypes(1);
22769 }
22770 if($Descriptor{2}{"Dump"})
22771 { # support for old ABI dumps
22772 prepareTypes(2);
22773 }
22774 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22775 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22776 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022777 # process input data
22778 if($Descriptor{1}{"Headers"}
22779 and not $Descriptor{1}{"Dump"}) {
22780 readHeaders(1);
22781 }
22782 if($Descriptor{2}{"Headers"}
22783 and not $Descriptor{2}{"Dump"}) {
22784 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022785 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022786
22787 # clean memory
22788 %SystemHeaders = ();
22789 %mangled_name_gcc = ();
22790
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022791 prepareSymbols(1);
22792 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022793
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022794 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022795 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022796
22797 # Virtual Tables
22798 registerVTable(1);
22799 registerVTable(2);
22800
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022801 if(not checkDump(1, "1.22")
22802 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022803 { # support for old ABI dumps
22804 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22805 {
22806 if($ClassName=~/</)
22807 { # templates
22808 if(not defined $VirtualTable{1}{$ClassName})
22809 { # synchronize
22810 delete($VirtualTable{2}{$ClassName});
22811 }
22812 }
22813 }
22814 }
22815
22816 registerOverriding(1);
22817 registerOverriding(2);
22818
22819 setVirtFuncPositions(1);
22820 setVirtFuncPositions(2);
22821
22822 # Other
22823 addParamNames(1);
22824 addParamNames(2);
22825
22826 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022827}
22828
22829sub compareAPIs($)
22830{
22831 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022832
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022833 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022834 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022835
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022836 if($Level eq "Binary") {
22837 printMsg("INFO", "comparing ABIs ...");
22838 }
22839 else {
22840 printMsg("INFO", "comparing APIs ...");
22841 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022843 if($CheckHeadersOnly
22844 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022845 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022846 detectAdded_H($Level);
22847 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022848 }
22849 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022850 { # added/removed in libs
22851 detectAdded($Level);
22852 detectRemoved($Level);
22853 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022854
22855 mergeSymbols($Level);
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022856
22857 if(not defined $DisableConstantsCheck)
22858 {
22859 if(keys(%{$CheckedSymbols{$Level}})) {
22860 mergeConstants($Level);
22861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022862 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022863
22864 $Cache{"mergeTypes"} = (); # free memory
22865
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022866 if($CheckHeadersOnly
22867 or $Level eq "Source")
22868 { # added/removed in headers
22869 mergeHeaders($Level);
22870 }
22871 else
22872 { # added/removed in libs
22873 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022874 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022875
22876 foreach my $S (keys(%{$CompatProblems{$Level}}))
22877 {
22878 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22879 {
22880 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22881 {
22882 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22883 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22884 }
22885 }
22886 }
22887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022888}
22889
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022890sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022891{
22892 my %Opts = (
22893 "OStarget"=>$OStarget,
22894 "Debug"=>$Debug,
22895 "Quiet"=>$Quiet,
22896 "LogMode"=>$LogMode,
22897 "CheckHeadersOnly"=>$CheckHeadersOnly,
22898
22899 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022900 "GCC_PATH"=>$GCC_PATH,
22901 "TargetSysInfo"=>$TargetSysInfo,
22902 "CrossPrefix"=>$CrossPrefix,
22903 "TargetLibraryName"=>$TargetLibraryName,
22904 "CrossGcc"=>$CrossGcc,
22905 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022906 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030022907 "CxxIncompat"=>$CxxIncompat,
22908 "SkipUnidentified"=>$SkipUnidentified,
Andrey Ponomarenko26742a82016-09-27 18:27:08 +030022909 "DisableConstantsCheck"=>$DisableConstantsCheck,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022910
22911 "BinaryOnly" => $BinaryOnly,
22912 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022913 );
22914 return \%Opts;
22915}
22916
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022917sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022918{
22919 my %CODE_ERROR = reverse(%ERROR_CODE);
22920 return $CODE_ERROR{$_[0]};
22921}
22922
22923sub scenario()
22924{
22925 if($StdOut)
22926 { # enable quiet mode
22927 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022928 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022929 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022930 if(not $LogMode)
22931 { # default
22932 $LogMode = "w";
22933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022934 if($UserLang)
22935 { # --lang=C++
22936 $UserLang = uc($UserLang);
22937 $COMMON_LANGUAGE{1}=$UserLang;
22938 $COMMON_LANGUAGE{2}=$UserLang;
22939 }
22940 if($LoggingPath)
22941 {
22942 $OutputLogPath{1} = $LoggingPath;
22943 $OutputLogPath{2} = $LoggingPath;
22944 if($Quiet) {
22945 $COMMON_LOG_PATH = $LoggingPath;
22946 }
22947 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022948
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022949 if($Quick) {
22950 $ADD_TMPL_INSTANCES = 0;
22951 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022952 if($OutputDumpPath)
22953 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022954 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022955 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22956 }
22957 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022958 if($BinaryOnly and $SourceOnly)
22959 { # both --binary and --source
22960 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022961 if(not $CmpSystems)
22962 {
22963 $BinaryOnly = 0;
22964 $SourceOnly = 0;
22965 }
22966
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022967 $DoubleReport = 1;
22968 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022969
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022970 if($OutputReportPath)
22971 { # --report-path
22972 $DoubleReport = 0;
22973 $JoinReport = 1;
22974 }
22975 }
22976 elsif($BinaryOnly or $SourceOnly)
22977 { # --binary or --source
22978 $DoubleReport = 0;
22979 $JoinReport = 0;
22980 }
22981 if($UseXML)
22982 { # --xml option
22983 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022984 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022986 if($ReportFormat)
22987 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022988 $ReportFormat = lc($ReportFormat);
22989 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022990 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022991 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022992 if($ReportFormat eq "htm")
22993 { # HTM == HTML
22994 $ReportFormat = "html";
22995 }
22996 elsif($ReportFormat eq "xml")
22997 { # --report-format=XML equal to --xml
22998 $UseXML = 1;
22999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023000 }
23001 else
23002 { # default: HTML
23003 $ReportFormat = "html";
23004 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023005 if($DumpFormat)
23006 { # validate
23007 $DumpFormat = lc($DumpFormat);
23008 if($DumpFormat!~/\A(xml|perl)\Z/) {
23009 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
23010 }
23011 if($DumpFormat eq "xml")
23012 { # --dump-format=XML equal to --xml
23013 $UseXML = 1;
23014 }
23015 }
23016 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040023017 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040023018 $DumpFormat = "perl";
23019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023020 if($Quiet and $LogMode!~/a|n/)
23021 { # --quiet log
23022 if(-f $COMMON_LOG_PATH) {
23023 unlink($COMMON_LOG_PATH);
23024 }
23025 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040023026 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023027 $CheckUndefined = 1;
23028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023029 if($TestTool and $UseDumps)
23030 { # --test && --use-dumps == --test-dump
23031 $TestDump = 1;
23032 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040023033 if($Tolerant)
23034 { # enable all
23035 $Tolerance = 1234;
23036 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023037 if($Help)
23038 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023039 HELP_MESSAGE();
23040 exit(0);
23041 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030023042 if($InfoMsg)
23043 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023044 INFO_MESSAGE();
23045 exit(0);
23046 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023047 if($ShowVersion)
23048 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023049 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 +040023050 exit(0);
23051 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023052 if($DumpVersion)
23053 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023054 printMsg("INFO", $TOOL_VERSION);
23055 exit(0);
23056 }
23057 if($ExtendedCheck) {
23058 $CheckHeadersOnly = 1;
23059 }
23060 if($SystemRoot_Opt)
23061 { # user defined root
23062 if(not -e $SystemRoot_Opt) {
23063 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
23064 }
23065 $SystemRoot = $SystemRoot_Opt;
23066 $SystemRoot=~s/[\/]+\Z//g;
23067 if($SystemRoot) {
23068 $SystemRoot = get_abs_path($SystemRoot);
23069 }
23070 }
23071 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023073 if($SortDump)
23074 {
23075 $Data::Dumper::Useperl = 1;
23076 $Data::Dumper::Sortkeys = \&dump_sorting;
23077 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023079 if($TargetLibsPath)
23080 {
23081 if(not -f $TargetLibsPath) {
23082 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
23083 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023084 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
23085 {
23086 if($OSgroup eq "windows") {
23087 $TargetLibs{lc($Lib)} = 1;
23088 }
23089 else {
23090 $TargetLibs{$Lib} = 1;
23091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023092 }
23093 }
23094 if($TargetHeadersPath)
23095 { # --headers-list
23096 if(not -f $TargetHeadersPath) {
23097 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
23098 }
23099 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
23100 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023101 $TargetHeaders{1}{get_filename($Header)} = 1;
23102 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023103 }
23104 }
23105 if($TargetHeader)
23106 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023107 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
23108 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023109 }
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023110 if($TestABIDumper)
23111 {
23112 if($OSgroup ne "linux") {
23113 exitStatus("Error", "-test-abi-dumper option is available on Linux only");
23114 }
23115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023116 if($TestTool
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023117 or $TestDump
23118 or $TestABIDumper)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023119 { # --test, --test-dump
23120 detect_default_paths("bin|gcc"); # to compile libs
23121 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023122 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko959dd192016-10-06 19:51:11 +030023123 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle, $TestABIDumper);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023124 exit(0);
23125 }
23126 if($DumpSystem)
23127 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023128 if(-d $MODULES_DIR."/Targets/"
23129 and -d $MODULES_DIR."/Targets/".$OStarget) {
23130 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
23131 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023132 if(not $TargetSysInfo) {
23133 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
23134 }
23135
23136 if(not -d $TargetSysInfo) {
23137 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23138 }
23139
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023140 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023141 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023142 { # system XML descriptor
23143 if(not -f $DumpSystem) {
23144 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23145 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023146
23147 my $SDesc = readFile($DumpSystem);
23148 if(my $RelDir = $RelativeDirectory{1}) {
23149 $SDesc =~ s/{RELPATH}/$RelDir/g;
23150 }
23151
23152 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023153 foreach (@{$Ret->{"Tools"}})
23154 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023155 push_U($SystemPaths{"bin"}, $_);
23156 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023157 }
23158 if($Ret->{"CrossPrefix"}) {
23159 $CrossPrefix = $Ret->{"CrossPrefix"};
23160 }
23161 }
23162 elsif($SystemRoot_Opt)
23163 { # -sysroot "/" option
23164 # default target: /usr/lib, /usr/include
23165 # search libs: /usr/lib and /lib
23166 if(not -e $SystemRoot."/usr/lib") {
23167 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23168 }
23169 if(not -e $SystemRoot."/lib") {
23170 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23171 }
23172 if(not -e $SystemRoot."/usr/include") {
23173 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23174 }
23175 readSystemDescriptor("
23176 <name>
23177 $DumpSystem
23178 </name>
23179 <headers>
23180 $SystemRoot/usr/include
23181 </headers>
23182 <libs>
23183 $SystemRoot/usr/lib
23184 </libs>
23185 <search_libs>
23186 $SystemRoot/lib
23187 </search_libs>");
23188 }
23189 else {
23190 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23191 }
23192 detect_default_paths("bin|gcc"); # to check symbols
23193 if($OStarget eq "windows")
23194 { # to run dumpbin.exe
23195 # and undname.exe
23196 check_win32_env();
23197 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023198 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023199 exit(0);
23200 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023201
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023202 if($CmpSystems)
23203 { # --cmp-systems
23204 detect_default_paths("bin"); # to extract dumps
23205 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023206 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023207 exit(0);
23208 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023209
23210 if(not $CountSymbols)
23211 {
23212 if(not $TargetLibraryName) {
23213 exitStatus("Error", "library name is not selected (-l option)");
23214 }
23215 else
23216 { # validate library name
23217 if($TargetLibraryName=~/[\*\/\\]/) {
23218 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023220 }
23221 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023222
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023223 if(not $TargetTitle) {
23224 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023225 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023226
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023227 if($SymbolsListPath)
23228 {
23229 if(not -f $SymbolsListPath) {
23230 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23231 }
23232 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23233 $SymbolsList{$Interface} = 1;
23234 }
23235 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023236 if($TypesListPath)
23237 {
23238 if(not -f $TypesListPath) {
23239 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23240 }
23241 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23242 $TypesList{$Type} = 1;
23243 }
23244 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023245 if($SkipSymbolsListPath)
23246 {
23247 if(not -f $SkipSymbolsListPath) {
23248 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23249 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023250 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23251 {
23252 $SkipSymbols{1}{$Interface} = 1;
23253 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023254 }
23255 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023256 if($SkipTypesListPath)
23257 {
23258 if(not -f $SkipTypesListPath) {
23259 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23260 }
23261 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23262 {
23263 $SkipTypes{1}{$Type} = 1;
23264 $SkipTypes{2}{$Type} = 1;
23265 }
23266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023267 if($SkipHeadersPath)
23268 {
23269 if(not -f $SkipHeadersPath) {
23270 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23271 }
23272 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023273 { # register for both versions
23274 $SkipHeadersList{1}{$Path} = 1;
23275 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023277 my ($CPath, $Type) = classifyPath($Path);
23278 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023279 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023280 }
23281 }
23282 if($ParamNamesPath)
23283 {
23284 if(not -f $ParamNamesPath) {
23285 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23286 }
23287 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23288 {
23289 if($Line=~s/\A(\w+)\;//)
23290 {
23291 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023292 if($Line=~/;(\d+);/)
23293 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023294 while($Line=~s/(\d+);(\w+)//) {
23295 $AddIntParams{$Interface}{$1}=$2;
23296 }
23297 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023298 else
23299 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023300 my $Num = 0;
23301 foreach my $Name (split(/;/, $Line)) {
23302 $AddIntParams{$Interface}{$Num++}=$Name;
23303 }
23304 }
23305 }
23306 }
23307 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023309 if($AppPath)
23310 {
23311 if(not -f $AppPath) {
23312 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23313 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023314
23315 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023316 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023317 $SymbolsList_App{$Interface} = 1;
23318 }
23319 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023320
23321 if($CountSymbols)
23322 {
23323 if(not -e $CountSymbols) {
23324 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23325 }
23326
23327 read_ABI_Dump(1, $CountSymbols);
23328
23329 foreach my $Id (keys(%{$SymbolInfo{1}}))
23330 {
23331 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23332 if(not $MnglName) {
23333 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23334 }
23335
23336 if(my $SV = $SymVer{1}{$MnglName}) {
23337 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23338 }
23339 else {
23340 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23341 }
23342
23343 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23344 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23345 }
23346 }
23347
23348 my $Count = 0;
23349 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23350 {
23351 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23352 next;
23353 }
23354 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23355 next;
23356 }
23357 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23358 next;
23359 }
23360
23361 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23362 }
23363
23364 printMsg("INFO", $Count);
23365 exit(0);
23366 }
23367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023368 if($DumpAPI)
23369 { # --dump-abi
23370 # make an API dump
23371 create_ABI_Dump();
23372 exit($COMPILE_ERRORS);
23373 }
23374 # default: compare APIs
23375 # -d1 <path>
23376 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023377 compareInit();
23378 if($JoinReport or $DoubleReport)
23379 {
23380 compareAPIs("Binary");
23381 compareAPIs("Source");
23382 }
23383 elsif($BinaryOnly) {
23384 compareAPIs("Binary");
23385 }
23386 elsif($SourceOnly) {
23387 compareAPIs("Source");
23388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023389 exitReport();
23390}
23391
23392scenario();