blob: 0dece16004218836415381172b4147ca263b76d9 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko8580e852016-08-19 19:11:48 +03003# ABI Compliance Checker (ABICC) 1.99.24
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030024# - ABI Dumper (0.99.15 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040025#
26# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040027# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040028# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040029#
30# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040031# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040032# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040033# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030034# - Sigcheck v2.52 or newer
35# - GnuWin Zip and UnZip
36# - Exuberant Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040037# - Add tool locations to the PATH environment variable
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030038# - Run vcvars64.bat (C:\Microsoft Visual Studio 9.0\VC\bin\)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040039#
40# This program is free software: you can redistribute it and/or modify
41# it under the terms of the GNU General Public License or the GNU Lesser
42# General Public License as published by the Free Software Foundation.
43#
44# This program is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47# GNU General Public License for more details.
48#
49# You should have received a copy of the GNU General Public License
50# and the GNU Lesser General Public License along with this program.
51# If not, see <http://www.gnu.org/licenses/>.
52###########################################################################
53use Getopt::Long;
54Getopt::Long::Configure ("posix_default", "no_ignore_case");
55use File::Path qw(mkpath rmtree);
56use File::Temp qw(tempdir);
57use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040058use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040059use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040060use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040061use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040062
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030063my $TOOL_VERSION = "1.99.24";
64my $ABI_DUMP_VERSION = "3.3";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030088$SkipHeadersPath, $CxxCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CxxIncompat,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030093$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030095$DisableQuickEmptyReport, $SkipTypedefUncover, $MinGWCompat, $SkipUnidentified);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040096
97my $CmdName = get_filename($0);
98my %OS_LibExt = (
99 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400100 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400101 "macos"=>"dylib",
102 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400103 "symbian"=>"dso",
104 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400105 },
106 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400107 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400108 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400109 "symbian"=>"lib",
110 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400111 }
112);
113
114my %OS_Archive = (
115 "windows"=>"zip",
116 "default"=>"tar.gz"
117);
118
119my %ERROR_CODE = (
120 # Compatible verdict
121 "Compatible"=>0,
122 "Success"=>0,
123 # Incompatible verdict
124 "Incompatible"=>1,
125 # Undifferentiated error code
126 "Error"=>2,
127 # System command is not found
128 "Not_Found"=>3,
129 # Cannot access input files
130 "Access_Error"=>4,
131 # Cannot compile header files
132 "Cannot_Compile"=>5,
133 # Header compiled with errors
134 "Compile_Error"=>6,
135 # Invalid input ABI dump
136 "Invalid_Dump"=>7,
137 # Incompatible version of ABI dump
138 "Dump_Version"=>8,
139 # Cannot find a module
140 "Module_Error"=>9,
141 # Empty intersection between
142 # headers and shared objects
143 "Empty_Intersection"=>10,
144 # Empty set of symbols in headers
145 "Empty_Set"=>11
146);
147
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300148my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400149
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400150my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400151A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300152Copyright (C) 2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153License: GNU LGPL or GNU GPL
154
155Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400156Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157
158OLD.xml and NEW.xml are XML-descriptors:
159
160 <version>
161 1.0
162 </version>
163
164 <headers>
165 /path/to/headers/
166 </headers>
167
168 <libs>
169 /path/to/libraries/
170 </libs>
171
172More info: $CmdName --help\n";
173
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400174if($#ARGV==-1)
175{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400176 printMsg("INFO", $ShortUsage);
177 exit(0);
178}
179
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400180GetOptions("h|help!" => \$Help,
181 "i|info!" => \$InfoMsg,
182 "v|version!" => \$ShowVersion,
183 "dumpversion!" => \$DumpVersion,
184# general options
185 "l|lib|library=s" => \$TargetLibraryName,
186 "d1|old|o=s" => \$Descriptor{1}{"Path"},
187 "d2|new|n=s" => \$Descriptor{2}{"Path"},
188 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400190 "app|application=s" => \$AppPath,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300191 "static|static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400192 "gcc-path|cross-gcc=s" => \$CrossGcc,
193 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
194 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400195 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300196 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
197 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400198 "s|strict!" => \$StrictCompat,
199 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300200 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400201 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300202 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400203 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400204 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400205 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400206 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400207 "show-retval!" => \$ShowRetVal,
208 "use-dumps!" => \$UseDumps,
209 "nostdinc!" => \$NoStdInc,
210 "dump-system=s" => \$DumpSystem,
211 "sysinfo=s" => \$TargetSysInfo,
212 "cmp-systems!" => \$CmpSystems,
213 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400214 "ext|extended!" => \$ExtendedCheck,
215 "q|quiet!" => \$Quiet,
216 "stdout!" => \$StdOut,
217 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400218 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400219 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400220 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400221 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400222 "binary|bin|abi!" => \$BinaryOnly,
223 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400224 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300225 "count-symbols=s" => \$CountSymbols,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300226 "old-style!" => \$OldStyle,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227# other options
228 "test!" => \$TestTool,
229 "test-dump!" => \$TestDump,
230 "debug!" => \$Debug,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300231 "cpp-compatible!" => \$CxxCompat,
232 "cxx-incompatible|cpp-incompatible!" => \$CxxIncompat,
233 "mingw-compatible!" => \$MinGWCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234 "p|params=s" => \$ParamNamesPath,
235 "relpath1|relpath=s" => \$RelativeDirectory{1},
236 "relpath2=s" => \$RelativeDirectory{2},
237 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400238 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400239 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400240 "bin-report-path=s" => \$BinaryReportPath,
241 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "log-path=s" => \$LoggingPath,
243 "log1-path=s" => \$OutputLogPath{1},
244 "log2-path=s" => \$OutputLogPath{2},
245 "logging-mode=s" => \$LogMode,
246 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300247 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400248 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400249 "extra-info=s" => \$ExtraInfo,
250 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400251 "force!" => \$Force,
252 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400253 "tolerant!" => \$Tolerant,
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300254 "skip-unidentified!" => \$SkipUnidentified,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400255 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400256 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300257 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400258 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300259 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
260 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300261 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300262 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400263) or ERR_MESSAGE();
264
265sub ERR_MESSAGE()
266{
267 printMsg("INFO", "\n".$ShortUsage);
268 exit($ERROR_CODE{"Error"});
269}
270
271my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
272my $SLIB_TYPE = $LIB_TYPE;
273if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
274{ # show as "shared" library
275 $SLIB_TYPE = "shared";
276}
277my $LIB_EXT = getLIB_EXT($OSgroup);
278my $AR_EXT = getAR_EXT($OSgroup);
279my $BYTE_SIZE = 8;
280my $COMMON_LOG_PATH = "logs/run.log";
281
282my $HelpMessage="
283NAME:
284 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400285 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400286
287DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400288 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400289 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
290 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
291 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
292 and/or source-level compatibility: changes in calling stack, v-table changes,
293 removed symbols, renamed fields, etc. Binary incompatibility may result in
294 crashing or incorrect behavior of applications built with an old version of
295 a library if they run on a new one. Source incompatibility may result in
296 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400297
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400298 The tool is intended for developers of software libraries and maintainers
299 of operating systems who are interested in ensuring backward compatibility,
300 i.e. allow old applications to run or to be recompiled with newer library
301 versions.
302
303 Also the tool can be used by ISVs for checking applications portability to
304 new library versions. Found issues can be taken into account when adapting
305 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400306
307 This tool is free software: you can redistribute it and/or modify it
308 under the terms of the GNU LGPL or GNU GPL.
309
310USAGE:
311 $CmdName [options]
312
313EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400314 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400315
316 OLD.xml and NEW.xml are XML-descriptors:
317
318 <version>
319 1.0
320 </version>
321
322 <headers>
323 /path1/to/header(s)/
324 /path2/to/header(s)/
325 ...
326 </headers>
327
328 <libs>
329 /path1/to/library(ies)/
330 /path2/to/library(ies)/
331 ...
332 </libs>
333
334INFORMATION OPTIONS:
335 -h|-help
336 Print this help.
337
338 -i|-info
339 Print complete info.
340
341 -v|-version
342 Print version information.
343
344 -dumpversion
345 Print the tool version ($TOOL_VERSION) and don't do anything else.
346
347GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400348 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400349 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400350
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400351 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400352 Descriptor of 1st (old) library version.
353 It may be one of the following:
354
355 1. XML-descriptor (VERSION.xml file):
356
357 <version>
358 1.0
359 </version>
360
361 <headers>
362 /path1/to/header(s)/
363 /path2/to/header(s)/
364 ...
365 </headers>
366
367 <libs>
368 /path1/to/library(ies)/
369 /path2/to/library(ies)/
370 ...
371 </libs>
372
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300373 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374
375 2. ABI dump generated by -dump option
376 3. Directory with headers and/or $SLIB_TYPE libraries
377 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400378
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300379 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400380 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400381
382 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400383 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400384
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400385 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400386 Descriptor of 2nd (new) library version.
387
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400388 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400389 Create library ABI dump for the input XML descriptor. You can
390 transfer it anywhere and pass instead of the descriptor. Also
391 it can be used for debugging the tool.
392
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300393 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400394
395sub HELP_MESSAGE() {
396 printMsg("INFO", $HelpMessage."
397MORE INFO:
398 $CmdName --info\n");
399}
400
401sub INFO_MESSAGE()
402{
403 printMsg("INFO", "$HelpMessage
404EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400405 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300406 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 for portability to the new library version.
408
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300409 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 Check static libraries instead of the shared ones. The <libs> section
411 of the XML-descriptor should point to static libraries location.
412
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300413 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414 Path to the cross GCC compiler to use instead of the usual (host) GCC.
415
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300416 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300418
419 -gcc-options OPTS
420 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400422 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400423 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400424 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400425
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400426 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400427 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200428 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429
430 In general case you should specify it in the XML-descriptor:
431 <version>
432 VERSION
433 </version>
434
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400435 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400436 Specify 2nd library version outside the descriptor.
437
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400438 -vnum NUM
439 Specify the library version in the generated ABI dump. The <version> section
440 of the input XML descriptor will be overwritten in this case.
441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400442 -s|-strict
443 Treat all compatibility warnings as problems. Add a number of \"Low\"
444 severity problems to the return value of the tool.
445
446 -headers-only
447 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
448 provide a low quality compatibility report with false positives and
449 without detecting of added/removed symbols.
450
451 Alternatively you can write \"none\" word to the <libs> section
452 in the XML-descriptor:
453 <libs>
454 none
455 </libs>
456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400457 -show-retval
458 Show the symbol's return type in the report.
459
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400460 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300461 This option allows to specify a file with a list of symbols (mangled
462 names in C++) that should be checked. Other symbols will not be checked.
463
464 -types-list PATH
465 This option allows to specify a file with a list of types that should
466 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400467
468 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300469 The list of symbols that should not be checked.
470
471 -skip-types PATH
472 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400473
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400474 -headers-list PATH
475 The file with a list of headers, that should be checked/dumped.
476
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400477 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400478 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400479
480 -header NAME
481 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400482
483 -use-dumps
484 Make dumps for two versions of a library and compare dumps. This should
485 increase the performance of the tool and decrease the system memory usage.
486
487 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400488 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400489
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400490 -dump-system NAME -sysroot DIR
491 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400492 create XML descriptors and make ABI dumps for each library. The result
493 set of ABI dumps can be compared (--cmp-systems) with the other one
494 created for other version of operating system in order to check them for
495 compatibility. Do not forget to specify -cross-gcc option if your target
496 system requires some specific version of GCC compiler (different from
497 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400498 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400500 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400501 The same as the previous option but takes an XML descriptor of the target
502 system as input, where you should describe it:
503
504 /* Primary sections */
505
506 <name>
507 /* Name of the system */
508 </name>
509
510 <headers>
511 /* The list of paths to header files and/or
512 directories with header files, one per line */
513 </headers>
514
515 <libs>
516 /* The list of paths to shared libraries and/or
517 directories with shared libraries, one per line */
518 </libs>
519
520 /* Optional sections */
521
522 <search_headers>
523 /* List of directories to be searched
524 for header files to automatically
525 generate include paths, one per line */
526 </search_headers>
527
528 <search_libs>
529 /* List of directories to be searched
530 for shared libraries to resolve
531 dependencies, one per line */
532 </search_libs>
533
534 <tools>
535 /* List of directories with tools used
536 for analysis (GCC toolchain), one per line */
537 </tools>
538
539 <cross_prefix>
540 /* GCC toolchain prefix.
541 Examples:
542 arm-linux-gnueabi
543 arm-none-symbianelf */
544 </cross_prefix>
545
546 <gcc_options>
547 /* Additional GCC options, one per line */
548 </gcc_options>
549
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400550 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300551 This option should be used with -dump-system option to dump
552 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400554 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300555 Compare two ABI dumps of a system. Create compatibility reports for
556 each system library and the common HTML report including the summary
557 of test results for all checked libraries.
558
559 Summary report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400560 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400561
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400562 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400563 The file with a list of libraries, that should be dumped by
564 the -dump-system option or should be checked by the -cmp-systems option.
565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400566 -ext|-extended
567 If your library A is supposed to be used by other library B and you
568 want to control the ABI of B, then you should enable this option. The
569 tool will check for changes in all data types, even if they are not
570 used by any function in the library A. Such data types are not part
571 of the A library ABI, but may be a part of the ABI of the B library.
572
573 The short scheme is:
574 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
575
576 -q|-quiet
577 Print all messages to the file instead of stdout and stderr.
578 Default path (can be changed by -log-path option):
579 $COMMON_LOG_PATH
580
581 -stdout
582 Print analysis results (compatibility reports and ABI dumps) to stdout
583 instead of creating a file. This would allow piping data to other programs.
584
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400585 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400586 Change format of compatibility report.
587 Formats:
588 htm - HTML format (default)
589 xml - XML format
590
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400591 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400592 Change format of ABI dump.
593 Formats:
594 perl - Data::Dumper format (default)
595 xml - XML format
596
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400597 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400598 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400599
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400600 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400601 Set library language (C or C++). You can use this option if the tool
602 cannot auto-detect a language. This option may be useful for checking
603 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400604
605 -arch ARCH
606 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
607 ect.). The option is useful if the tool cannot detect correct architecture
608 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400609
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400610 -binary|-bin|-abi
611 Show \"Binary\" compatibility problems only.
612 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400613 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400614
615 -source|-src|-api
616 Show \"Source\" compatibility problems only.
617 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400618 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400619
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400620 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400621 The maximum number of affected symbols listed under the description
622 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300623
624 -count-symbols PATH
625 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300626
627 -old-style
628 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400630OTHER OPTIONS:
631 -test
632 Run internal tests. Create two binary incompatible versions of a sample
633 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300634 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400635
636 -test-dump
637 Test ability to create, read and compare ABI dumps.
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400639 -debug
640 Debugging mode. Print debug info on the screen. Save intermediate
641 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400642 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400643
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400644 Also consider using --dump option for debugging the tool.
645
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400646 -cpp-compatible
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300647 Do nothing.
648
649 -cxx-incompatible
650 Set this option if input C header files use C++ keywords. The tool
651 will try to replace such keywords at preprocessor stage and replace
652 them back in the final TU dump.
653
654 -mingw-compatible
655 If input header files are compatible with the MinGW GCC compiler,
656 then you can tell the tool about this and speedup the analysis .
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400657
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400658 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 Path to file with the function parameter names. It can be used
660 for improving report view if the library header files have no
661 parameter names. File format:
662
663 func1;param1;param2;param3 ...
664 func2;param1;param2;param3 ...
665 ...
666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -relpath PATH
668 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 for dumping the library ABI (see -dump option).
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300670
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 -relpath1 PATH
672 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 -relpath2 PATH
675 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400678 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400682 -sort
683 Enable sorting of data in ABI dumps.
684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400686 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400687 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400691 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400696 Path to \"Source\" compatibility report.
697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Log path for all messages.
702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400706 Log path for 1st version of a library.
707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 Log path for 2nd version of a library.
712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716 Change logging mode.
717 Modes:
718 w - overwrite old logs (default)
719 a - append old logs
720 n - do not write any logs
721
722 -list-affected
723 Generate file with the list of incompatible
724 symbols beside the HTML compatibility report.
725 Use 'c++filt \@file' command from GNU binutils
726 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400727 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400728 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400729 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400730
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732 The component name in the title and summary of the HTML report.
733 Default:
734 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300735
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300736 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400737 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400738 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400739
740 -extra-info DIR
741 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400742
743 -extra-dump
744 Create extended ABI dump containing all symbols
745 from the translation unit.
746
747 -force
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300748 Try to enable this option if the tool checked zero
749 types and symbols in header files.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400750
751 -tolerance LEVEL
752 Apply a set of heuristics to successfully compile input
753 header files. You can enable several tolerance levels by
754 joining them into one string (e.g. 13, 124, etc.).
755 Levels:
756 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
757 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900758 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400759 4 - skip headers included by others
760
761 -tolerant
762 Enable highest tolerance level [1234].
Andrey Ponomarenko991da682016-09-07 19:09:50 +0300763
764 -skip-unidentified
765 Skip header files in 'headers' and 'include_preamble' sections
766 of the XML descriptor that cannot be found. This is useful if
767 you are trying to use the same descriptor for different targets.
768
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400769 -check
770 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400771
772 -quick
773 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300774
775 -disable-quick-empty-report
776 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400777
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300778 -skip-internal-symbols PATTERN
779 Do not check symbols matched by the pattern.
780
781 -skip-internal-types PATTERN
782 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300783
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300784 -skip-typedef-uncover
785 Do not report a problem if type is covered or
786 uncovered by typedef (useful for broken debug info).
787
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300788 -check-private-abi
789 Check data types from the private part of the ABI when
790 comparing ABI dumps created by the ABI Dumper tool with
791 use of the -public-headers option.
792
793 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400794
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400795REPORT:
796 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400797 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400798
799 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400800 logs/LIB_NAME/V1/log.txt
801 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400802
803EXIT CODES:
804 0 - Compatible. The tool has run without any errors.
805 non-zero - Incompatible or the tool has run with errors.
806
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400807MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300808 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400809}
810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400811my %Operator_Indication = (
812 "not" => "~",
813 "assign" => "=",
814 "andassign" => "&=",
815 "orassign" => "|=",
816 "xorassign" => "^=",
817 "or" => "|",
818 "xor" => "^",
819 "addr" => "&",
820 "and" => "&",
821 "lnot" => "!",
822 "eq" => "==",
823 "ne" => "!=",
824 "lt" => "<",
825 "lshift" => "<<",
826 "lshiftassign" => "<<=",
827 "rshiftassign" => ">>=",
828 "call" => "()",
829 "mod" => "%",
830 "modassign" => "%=",
831 "subs" => "[]",
832 "land" => "&&",
833 "lor" => "||",
834 "rshift" => ">>",
835 "ref" => "->",
836 "le" => "<=",
837 "deref" => "*",
838 "mult" => "*",
839 "preinc" => "++",
840 "delete" => " delete",
841 "vecnew" => " new[]",
842 "vecdelete" => " delete[]",
843 "predec" => "--",
844 "postinc" => "++",
845 "postdec" => "--",
846 "plusassign" => "+=",
847 "plus" => "+",
848 "minus" => "-",
849 "minusassign" => "-=",
850 "gt" => ">",
851 "ge" => ">=",
852 "new" => " new",
853 "multassign" => "*=",
854 "divassign" => "/=",
855 "div" => "/",
856 "neg" => "-",
857 "pos" => "+",
858 "memref" => "->*",
859 "compound" => "," );
860
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400861my %UnknownOperator;
862
863my %NodeType= (
864 "array_type" => "Array",
865 "binfo" => "Other",
866 "boolean_type" => "Intrinsic",
867 "complex_type" => "Intrinsic",
868 "const_decl" => "Other",
869 "enumeral_type" => "Enum",
870 "field_decl" => "Other",
871 "function_decl" => "Other",
872 "function_type" => "FunctionType",
873 "identifier_node" => "Other",
874 "integer_cst" => "Other",
875 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400876 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400877 "method_type" => "MethodType",
878 "namespace_decl" => "Other",
879 "parm_decl" => "Other",
880 "pointer_type" => "Pointer",
881 "real_cst" => "Other",
882 "real_type" => "Intrinsic",
883 "record_type" => "Struct",
884 "reference_type" => "Ref",
885 "string_cst" => "Other",
886 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400887 "template_type_parm" => "TemplateParam",
888 "typename_type" => "TypeName",
889 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400890 "tree_list" => "Other",
891 "tree_vec" => "Other",
892 "type_decl" => "Other",
893 "union_type" => "Union",
894 "var_decl" => "Other",
895 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400896 "nop_expr" => "Other", #
897 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400898 "offset_type" => "Other" );
899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400900my %CppKeywords_C = map {$_=>1} (
901 # C++ 2003 keywords
902 "public",
903 "protected",
904 "private",
905 "default",
906 "template",
907 "new",
908 #"asm",
909 "dynamic_cast",
910 "auto",
911 "try",
912 "namespace",
913 "typename",
914 "using",
915 "reinterpret_cast",
916 "friend",
917 "class",
918 "virtual",
919 "const_cast",
920 "mutable",
921 "static_cast",
922 "export",
923 # C++0x keywords
924 "noexcept",
925 "nullptr",
926 "constexpr",
927 "static_assert",
928 "explicit",
929 # cannot be used as a macro name
930 # as it is an operator in C++
931 "and",
932 #"and_eq",
933 "not",
934 #"not_eq",
935 "or"
936 #"or_eq",
937 #"bitand",
938 #"bitor",
939 #"xor",
940 #"xor_eq",
941 #"compl"
942);
943
944my %CppKeywords_F = map {$_=>1} (
945 "delete",
946 "catch",
947 "alignof",
948 "thread_local",
949 "decltype",
950 "typeid"
951);
952
953my %CppKeywords_O = map {$_=>1} (
954 "bool",
955 "register",
956 "inline",
957 "operator"
958);
959
960my %CppKeywords_A = map {$_=>1} (
961 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400962 "throw",
963 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400964);
965
966foreach (keys(%CppKeywords_C),
967keys(%CppKeywords_F),
968keys(%CppKeywords_O)) {
969 $CppKeywords_A{$_}=1;
970}
971
972# Header file extensions as described by gcc
973my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
974
975my %IntrinsicMangling = (
976 "void" => "v",
977 "bool" => "b",
978 "wchar_t" => "w",
979 "char" => "c",
980 "signed char" => "a",
981 "unsigned char" => "h",
982 "short" => "s",
983 "unsigned short" => "t",
984 "int" => "i",
985 "unsigned int" => "j",
986 "long" => "l",
987 "unsigned long" => "m",
988 "long long" => "x",
989 "__int64" => "x",
990 "unsigned long long" => "y",
991 "__int128" => "n",
992 "unsigned __int128" => "o",
993 "float" => "f",
994 "double" => "d",
995 "long double" => "e",
996 "__float80" => "e",
997 "__float128" => "g",
998 "..." => "z"
999);
1000
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001001my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001003my %StdcxxMangling = (
1004 "3std"=>"St",
1005 "3std9allocator"=>"Sa",
1006 "3std12basic_string"=>"Sb",
1007 "3std12basic_stringIcE"=>"Ss",
1008 "3std13basic_istreamIcE"=>"Si",
1009 "3std13basic_ostreamIcE"=>"So",
1010 "3std14basic_iostreamIcE"=>"Sd"
1011);
1012
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001013my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001014my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1015
1016my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001017my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001019my %ConstantSuffix = (
1020 "unsigned int"=>"u",
1021 "long"=>"l",
1022 "unsigned long"=>"ul",
1023 "long long"=>"ll",
1024 "unsigned long long"=>"ull"
1025);
1026
1027my %ConstantSuffixR =
1028reverse(%ConstantSuffix);
1029
1030my %OperatorMangling = (
1031 "~" => "co",
1032 "=" => "aS",
1033 "|" => "or",
1034 "^" => "eo",
1035 "&" => "an",#ad (addr)
1036 "==" => "eq",
1037 "!" => "nt",
1038 "!=" => "ne",
1039 "<" => "lt",
1040 "<=" => "le",
1041 "<<" => "ls",
1042 "<<=" => "lS",
1043 ">" => "gt",
1044 ">=" => "ge",
1045 ">>" => "rs",
1046 ">>=" => "rS",
1047 "()" => "cl",
1048 "%" => "rm",
1049 "[]" => "ix",
1050 "&&" => "aa",
1051 "||" => "oo",
1052 "*" => "ml",#de (deref)
1053 "++" => "pp",#
1054 "--" => "mm",#
1055 "new" => "nw",
1056 "delete" => "dl",
1057 "new[]" => "na",
1058 "delete[]" => "da",
1059 "+=" => "pL",
1060 "+" => "pl",#ps (pos)
1061 "-" => "mi",#ng (neg)
1062 "-=" => "mI",
1063 "*=" => "mL",
1064 "/=" => "dV",
1065 "&=" => "aN",
1066 "|=" => "oR",
1067 "%=" => "rM",
1068 "^=" => "eO",
1069 "/" => "dv",
1070 "->*" => "pm",
1071 "->" => "pt",#rf (ref)
1072 "," => "cm",
1073 "?" => "qu",
1074 "." => "dt",
1075 "sizeof"=> "sz"#st
1076);
1077
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001078my %Intrinsic_Keywords = map {$_=>1} (
1079 "true",
1080 "false",
1081 "_Bool",
1082 "_Complex",
1083 "const",
1084 "int",
1085 "long",
1086 "void",
1087 "short",
1088 "float",
1089 "volatile",
1090 "restrict",
1091 "unsigned",
1092 "signed",
1093 "char",
1094 "double",
1095 "class",
1096 "struct",
1097 "union",
1098 "enum"
1099);
1100
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001101my %GlibcHeader = map {$_=>1} (
1102 "aliases.h",
1103 "argp.h",
1104 "argz.h",
1105 "assert.h",
1106 "cpio.h",
1107 "ctype.h",
1108 "dirent.h",
1109 "envz.h",
1110 "errno.h",
1111 "error.h",
1112 "execinfo.h",
1113 "fcntl.h",
1114 "fstab.h",
1115 "ftw.h",
1116 "glob.h",
1117 "grp.h",
1118 "iconv.h",
1119 "ifaddrs.h",
1120 "inttypes.h",
1121 "langinfo.h",
1122 "limits.h",
1123 "link.h",
1124 "locale.h",
1125 "malloc.h",
1126 "math.h",
1127 "mntent.h",
1128 "monetary.h",
1129 "nl_types.h",
1130 "obstack.h",
1131 "printf.h",
1132 "pwd.h",
1133 "regex.h",
1134 "sched.h",
1135 "search.h",
1136 "setjmp.h",
1137 "shadow.h",
1138 "signal.h",
1139 "spawn.h",
1140 "stdarg.h",
1141 "stdint.h",
1142 "stdio.h",
1143 "stdlib.h",
1144 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001145 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001146 "tar.h",
1147 "termios.h",
1148 "time.h",
1149 "ulimit.h",
1150 "unistd.h",
1151 "utime.h",
1152 "wchar.h",
1153 "wctype.h",
1154 "wordexp.h" );
1155
1156my %GlibcDir = map {$_=>1} (
1157 "arpa",
1158 "bits",
1159 "gnu",
1160 "netinet",
1161 "net",
1162 "nfs",
1163 "rpc",
1164 "sys",
1165 "linux" );
1166
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001167my %WinHeaders = map {$_=>1} (
1168 "dos.h",
1169 "process.h",
1170 "winsock.h",
1171 "config-win.h",
1172 "mem.h",
1173 "windows.h",
1174 "winsock2.h",
1175 "crtdbg.h",
1176 "ws2tcpip.h"
1177);
1178
1179my %ObsoleteHeaders = map {$_=>1} (
1180 "iostream.h",
1181 "fstream.h"
1182);
1183
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001184my %AlienHeaders = map {$_=>1} (
1185 # Solaris
1186 "thread.h",
1187 "sys/atomic.h",
1188 # HPUX
1189 "sys/stream.h",
1190 # Symbian
1191 "AknDoc.h",
1192 # Atari ST
1193 "ext.h",
1194 "tos.h",
1195 # MS-DOS
1196 "alloc.h",
1197 # Sparc
1198 "sys/atomic.h"
1199);
1200
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001201my %ConfHeaders = map {$_=>1} (
1202 "atomic",
1203 "conf.h",
1204 "config.h",
1205 "configure.h",
1206 "build.h",
1207 "setup.h"
1208);
1209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001210my %LocalIncludes = map {$_=>1} (
1211 "/usr/local/include",
1212 "/usr/local" );
1213
1214my %OS_AddPath=(
1215# These paths are needed if the tool cannot detect them automatically
1216 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001217 "include"=>[
1218 "/Library",
1219 "/Developer/usr/include"
1220 ],
1221 "lib"=>[
1222 "/Library",
1223 "/Developer/usr/lib"
1224 ],
1225 "bin"=>[
1226 "/Developer/usr/bin"
1227 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001228 },
1229 "beos"=>{
1230 # Haiku has GCC 2.95.3 by default
1231 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001232 "include"=>[
1233 "/boot/common",
1234 "/boot/develop"
1235 ],
1236 "lib"=>[
1237 "/boot/common/lib",
1238 "/boot/system/lib",
1239 "/boot/apps"
1240 ],
1241 "bin"=>[
1242 "/boot/common/bin",
1243 "/boot/system/bin",
1244 "/boot/develop/abi"
1245 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001247);
1248
1249my %Slash_Type=(
1250 "default"=>"/",
1251 "windows"=>"\\"
1252);
1253
1254my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1255
1256# Global Variables
1257my %COMMON_LANGUAGE=(
1258 1 => "C",
1259 2 => "C" );
1260
1261my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001262my $MAX_CPPFILT_FILE_SIZE = 50000;
1263my $CPPFILT_SUPPORT_FILE;
1264
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +03001265my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION, %CLANG_VERSION);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001267my $STDCXX_TESTING = 0;
1268my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001269my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001270
1271my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001272my $CheckUndefined = 0;
1273
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001274my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001275if($TargetComponent_Opt) {
1276 $TargetComponent = lc($TargetComponent_Opt);
1277}
1278else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001279{ # default: library
1280 # other components: header, system, ...
1281 $TargetComponent = "library";
1282}
1283
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001284my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001285
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001286my $SystemRoot;
1287
1288my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001289my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001290my %LOG_PATH;
1291my %DEBUG_PATH;
1292my %Cache;
1293my %LibInfo;
1294my $COMPILE_ERRORS = 0;
1295my %CompilerOptions;
1296my %CheckedDyLib;
1297my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1298
1299# Constants (#defines)
1300my %Constants;
1301my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001302my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001303
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001304# Extra Info
1305my %SymbolHeader;
1306my %KnownLibs;
1307
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001308# Templates
1309my %TemplateInstance;
1310my %BasicTemplate;
1311my %TemplateArg;
1312my %TemplateDecl;
1313my %TemplateMap;
1314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001315# Types
1316my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001317my %SkipTypes = (
1318 "1"=>{},
1319 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001320my %CheckedTypes;
1321my %TName_Tid;
1322my %EnumMembName_Id;
1323my %NestedNameSpaces = (
1324 "1"=>{},
1325 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001326my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001327my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001328my %ClassVTable;
1329my %ClassVTable_Content;
1330my %VTableClass;
1331my %AllocableClass;
1332my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001333my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001334my %Class_SubClasses;
1335my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001336my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001337my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001338
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001339my %CheckedTypeInfo;
1340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341# Typedefs
1342my %Typedef_BaseName;
1343my %Typedef_Tr;
1344my %Typedef_Eq;
1345my %StdCxxTypedef;
1346my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001347my %MissedBase;
1348my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001349my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001350
1351# Symbols
1352my %SymbolInfo;
1353my %tr_name;
1354my %mangled_name_gcc;
1355my %mangled_name;
1356my %SkipSymbols = (
1357 "1"=>{},
1358 "2"=>{} );
1359my %SkipNameSpaces = (
1360 "1"=>{},
1361 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001362my %AddNameSpaces = (
1363 "1"=>{},
1364 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001365my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001366my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001367my %SymbolsList_App;
1368my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001369my %Symbol_Library = (
1370 "1"=>{},
1371 "2"=>{} );
1372my %Library_Symbol = (
1373 "1"=>{},
1374 "2"=>{} );
1375my %DepSymbol_Library = (
1376 "1"=>{},
1377 "2"=>{} );
1378my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001379 "1"=>{},
1380 "2"=>{} );
1381my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001382my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001383my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001384my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001385my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001386my %Library_Needed= (
1387 "1"=>{},
1388 "2"=>{} );
Andrey Ponomarenko991da682016-09-07 19:09:50 +03001389my $DisabledMSVCUnmangling = undef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001390
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001391# Extra Info
1392my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001393my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001395# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001396my %Include_Preamble = (
1397 "1"=>[],
1398 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001399my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001400my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001401my %HeaderName_Paths;
1402my %Header_Dependency;
1403my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001404my %Include_Paths = (
1405 "1"=>[],
1406 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001407my %INC_PATH_AUTODETECT = (
1408 "1"=>1,
1409 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001410my %Add_Include_Paths = (
1411 "1"=>[],
1412 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413my %Skip_Include_Paths;
1414my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001415my %Header_ErrorRedirect;
1416my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001417my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418my %Header_ShouldNotBeUsed;
1419my %RecursiveIncludes;
1420my %Header_Include_Prefix;
1421my %SkipHeaders;
1422my %SkipHeadersList=(
1423 "1"=>{},
1424 "2"=>{} );
1425my %SkipLibs;
1426my %Include_Order;
1427my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001428my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001429my %TUnit_Funcs;
1430my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001431
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001432my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001433 "1"=>0,
1434 "2"=>0 );
1435my %AutoPreambleMode = (
1436 "1"=>0,
1437 "2"=>0 );
1438my %MinGWMode = (
1439 "1"=>0,
1440 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001441my %Cpp0xMode = (
1442 "1"=>0,
1443 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001444
1445# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001446my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001447my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001448my %RegisteredSONAMEs;
1449my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001451my %CheckedArch;
1452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453# System Objects
1454my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001455my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001456my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001457
1458# System Headers
1459my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001460my @DefaultCppPaths;
1461my @DefaultGccPaths;
1462my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001463my %DefaultCppHeader;
1464my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001465my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001466
1467# Merging
1468my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001469my $Version;
1470my %AddedInt;
1471my %RemovedInt;
1472my %AddedInt_Virt;
1473my %RemovedInt_Virt;
1474my %VirtualReplacement;
1475my %ChangedTypedef;
1476my %CompatRules;
1477my %IncompleteRules;
1478my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001479my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001480my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001481my %ReturnedClass;
1482my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001483my %SourceAlternative;
1484my %SourceAlternative_B;
1485my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001486my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001488#Report
1489my %TypeChanges;
1490
1491#Speedup
1492my %TypeProblemsIndex;
1493
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001494# Calling Conventions
1495my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001496 1=>{ "R"=>0, "P"=>0 },
1497 2=>{ "R"=>0, "P"=>0 }
1498);
1499
1500# ABI Dump
1501my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001502
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001503# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001504my %TargetLibs;
1505my %TargetHeaders;
1506
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001507# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508my $OStarget = $OSgroup;
1509my %TargetTools;
1510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001511# Recursion locks
1512my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001513my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001514my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001515my @RecurInclude;
1516my @RecurConstant;
1517
1518# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001519my %SystemPaths = (
1520 "include"=>[],
1521 "lib"=>[],
1522 "bin"=>[]
1523);
1524my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my $GCC_PATH;
1526
1527# Symbols versioning
1528my %SymVer = (
1529 "1"=>{},
1530 "2"=>{} );
1531
1532# Problem descriptions
1533my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001534my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001535my %TotalAffected;
1536
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001537# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538my $ContentID = 1;
1539my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001540my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1541my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001542my $ContentSpanEnd = "</span>\n";
1543my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1544my $ContentDivEnd = "</div>\n";
1545my $Content_Counter = 0;
1546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001547# Modes
1548my $JoinReport = 1;
1549my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001550
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001551my %Severity_Val=(
1552 "High"=>3,
1553 "Medium"=>2,
1554 "Low"=>1,
1555 "Safe"=>-1
1556);
1557
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001558sub get_Modules()
1559{
1560 my $TOOL_DIR = get_dirname($0);
1561 if(not $TOOL_DIR)
1562 { # patch for MS Windows
1563 $TOOL_DIR = ".";
1564 }
1565 my @SEARCH_DIRS = (
1566 # tool's directory
1567 abs_path($TOOL_DIR),
1568 # relative path to modules
1569 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001570 # install path
1571 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001572 );
1573 foreach my $DIR (@SEARCH_DIRS)
1574 {
1575 if(not is_abs($DIR))
1576 { # relative path
1577 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1578 }
1579 if(-d $DIR."/modules") {
1580 return $DIR."/modules";
1581 }
1582 }
1583 exitStatus("Module_Error", "can't find modules");
1584}
1585
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001586my %LoadedModules = ();
1587
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001588sub loadModule($)
1589{
1590 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001591 if(defined $LoadedModules{$Name}) {
1592 return;
1593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001594 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1595 if(not -f $Path) {
1596 exitStatus("Module_Error", "can't access \'$Path\'");
1597 }
1598 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001599 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001600}
1601
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001602sub readModule($$)
1603{
1604 my ($Module, $Name) = @_;
1605 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1606 if(not -f $Path) {
1607 exitStatus("Module_Error", "can't access \'$Path\'");
1608 }
1609 return readFile($Path);
1610}
1611
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001612sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001613{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001614 my $Number = $_[0];
1615 if(not $Number) {
1616 $Number = 1;
1617 }
1618 else {
1619 $Number = int($Number)+1;
1620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621 if($Number>3) {
1622 return $Number."th";
1623 }
1624 elsif($Number==1) {
1625 return "1st";
1626 }
1627 elsif($Number==2) {
1628 return "2nd";
1629 }
1630 elsif($Number==3) {
1631 return "3rd";
1632 }
1633 else {
1634 return $Number;
1635 }
1636}
1637
1638sub search_Tools($)
1639{
1640 my $Name = $_[0];
1641 return "" if(not $Name);
1642 if(my @Paths = keys(%TargetTools))
1643 {
1644 foreach my $Path (@Paths)
1645 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001646 if(-f join_P($Path, $Name)) {
1647 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001648 }
1649 if($CrossPrefix)
1650 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001651 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001652 if(-f $Candidate) {
1653 return $Candidate;
1654 }
1655 }
1656 }
1657 }
1658 else {
1659 return "";
1660 }
1661}
1662
1663sub synch_Cmd($)
1664{
1665 my $Name = $_[0];
1666 if(not $GCC_PATH)
1667 { # GCC was not found yet
1668 return "";
1669 }
1670 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001671 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001672 return $Candidate;
1673 }
1674 return "";
1675}
1676
1677sub get_CmdPath($)
1678{
1679 my $Name = $_[0];
1680 return "" if(not $Name);
1681 if(defined $Cache{"get_CmdPath"}{$Name}) {
1682 return $Cache{"get_CmdPath"}{$Name};
1683 }
1684 my %BinUtils = map {$_=>1} (
1685 "c++filt",
1686 "objdump",
1687 "readelf"
1688 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001689 if($BinUtils{$Name} and $GCC_PATH)
1690 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001691 if(my $Dir = get_dirname($GCC_PATH)) {
1692 $TargetTools{$Dir}=1;
1693 }
1694 }
1695 my $Path = search_Tools($Name);
1696 if(not $Path and $OSgroup eq "windows") {
1697 $Path = search_Tools($Name.".exe");
1698 }
1699 if(not $Path and $BinUtils{$Name})
1700 {
1701 if($CrossPrefix)
1702 { # user-defined prefix
1703 $Path = search_Cmd($CrossPrefix."-".$Name);
1704 }
1705 }
1706 if(not $Path and $BinUtils{$Name})
1707 {
1708 if(my $Candidate = synch_Cmd($Name))
1709 { # synch with GCC
1710 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001711 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 if(-f $Candidate) {
1713 $Path = $Candidate;
1714 }
1715 }
1716 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001717 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001718 $Path = $Candidate;
1719 }
1720 }
1721 }
1722 if(not $Path) {
1723 $Path = search_Cmd($Name);
1724 }
1725 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001726 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001727 $Path=search_Cmd($Name.".exe");
1728 }
1729 if($Path=~/\s/) {
1730 $Path = "\"".$Path."\"";
1731 }
1732 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1733}
1734
1735sub search_Cmd($)
1736{
1737 my $Name = $_[0];
1738 return "" if(not $Name);
1739 if(defined $Cache{"search_Cmd"}{$Name}) {
1740 return $Cache{"search_Cmd"}{$Name};
1741 }
1742 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1743 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1744 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001745 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001747 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 if(-f $CmdPath)
1749 {
1750 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001751 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001752 }
1753 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1754 }
1755 }
1756 return ($Cache{"search_Cmd"}{$Name} = "");
1757}
1758
1759sub get_CmdPath_Default($)
1760{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001761 return "" if(not $_[0]);
1762 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1763 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001764 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001765 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1766}
1767
1768sub get_CmdPath_Default_I($)
1769{ # search in PATH
1770 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001771 if($Name=~/find/)
1772 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001773 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001774 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001775 }
1776 }
1777 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001778 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001779 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001780 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001781 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001782 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001783 if($OSgroup eq "windows")
1784 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001785 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001786 return $Name;
1787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001788 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001789 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001790 {
1791 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001792 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001793 }
1794 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001795 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796}
1797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001798sub classifyPath($)
1799{
1800 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001801 if($Path=~/[\*\+\(\[\|]/)
1802 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 return ($Path, "Pattern");
1804 }
1805 elsif($Path=~/[\/\\]/)
1806 { # directory or relative path
1807 return (path_format($Path, $OSgroup), "Path");
1808 }
1809 else {
1810 return ($Path, "Name");
1811 }
1812}
1813
1814sub readDescriptor($$)
1815{
1816 my ($LibVersion, $Content) = @_;
1817 return if(not $LibVersion);
1818 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1819 if(not $Content) {
1820 exitStatus("Error", "$DName is empty");
1821 }
1822 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001823 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 }
1825 $Content=~s/\/\*(.|\n)+?\*\///g;
1826 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001828 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1829 if($TargetVersion{$LibVersion}) {
1830 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1831 }
1832 if(not $Descriptor{$LibVersion}{"Version"}) {
1833 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1834 }
1835 if($Content=~/{RELPATH}/)
1836 {
1837 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1838 $Content =~ s/{RELPATH}/$RelDir/g;
1839 }
1840 else
1841 {
1842 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1843 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1844 }
1845 }
1846
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001847 my $DHeaders = parseTag(\$Content, "headers");
1848 if(not $DHeaders) {
1849 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1850 }
1851 elsif(lc($DHeaders) ne "none")
1852 { # append the descriptor headers list
1853 if($Descriptor{$LibVersion}{"Headers"})
1854 { # multiple descriptors
1855 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001856 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001857 else {
1858 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1859 }
1860 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1861 {
1862 if(not -e $Path) {
1863 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 }
1865 }
1866 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001868 if(not $CheckHeadersOnly_Opt)
1869 {
1870 my $DObjects = parseTag(\$Content, "libs");
1871 if(not $DObjects) {
1872 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1873 }
1874 elsif(lc($DObjects) ne "none")
1875 { # append the descriptor libraries list
1876 if($Descriptor{$LibVersion}{"Libs"})
1877 { # multiple descriptors
1878 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1879 }
1880 else {
1881 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1882 }
1883 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1884 {
1885 if(not -e $Path) {
1886 exitStatus("Access_Error", "can't access \'$Path\'");
1887 }
1888 }
1889 }
1890 }
1891 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1892 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 if(not -d $Path) {
1894 exitStatus("Access_Error", "can't access directory \'$Path\'");
1895 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001896 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001898 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 }
1900 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1901 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001902 if(not -d $Path) {
1903 exitStatus("Access_Error", "can't access directory \'$Path\'");
1904 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001905 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001907 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001908 }
1909 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1910 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 if(not -d $Path) {
1912 exitStatus("Access_Error", "can't access directory \'$Path\'");
1913 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001914 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001915 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001916 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001917 $TargetTools{$Path}=1;
1918 }
1919 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1920 $CrossPrefix = $Prefix;
1921 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001922 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1924 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001925 if(not -d $Path) {
1926 exitStatus("Access_Error", "can't access directory \'$Path\'");
1927 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001928 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001930 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001931 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001932 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001933 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1934 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001935 if(not -d $Path) {
1936 exitStatus("Access_Error", "can't access directory \'$Path\'");
1937 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001938 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001939 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001940 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001941 }
1942 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001943 { # skip some auto-generated include paths
1944 if(not is_abs($Path))
1945 {
1946 if(my $P = abs_path($Path)) {
1947 $Path = $P;
1948 }
1949 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001950 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001951 }
1952 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001953 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001954 my ($CPath, $Type) = classifyPath($Path);
1955 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001956 }
1957 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001958 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1959 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001960 if($Option!~/\A\-(Wl|l|L)/)
1961 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001962 $CompilerOptions{$LibVersion} .= " ".$Option;
1963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001964 }
1965 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1966 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1967 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001968 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001969
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001970 my ($CPath, $Type) = classifyPath($Path);
1971 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 }
1973 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1974 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1975 {
1976 my ($CPath, $Type) = classifyPath($Path);
1977 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1978 }
1979 if(my $DDefines = parseTag(\$Content, "defines"))
1980 {
1981 if($Descriptor{$LibVersion}{"Defines"})
1982 { # multiple descriptors
1983 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1984 }
1985 else {
1986 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1987 }
1988 }
1989 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1990 {
1991 if($Order=~/\A(.+):(.+)\Z/) {
1992 $Include_Order{$LibVersion}{$1} = $2;
1993 }
1994 }
1995 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1996 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001997 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001998 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1999 }
2000 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2001 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002002 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002003 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2004 }
2005 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2006 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2007 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002008 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2009 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002011 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2012 $SkipConstants{$LibVersion}{$Constant} = 1;
2013 }
2014 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2015 {
2016 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002017 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002018 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2019 }
2020 else {
2021 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2022 }
2023 }
2024}
2025
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002026sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002027{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002028 my $CodeRef = shift(@_);
2029 my $Tag = shift(@_);
2030 if(not $Tag or not $CodeRef) {
2031 return undef;
2032 }
2033 my $Sp = 0;
2034 if(@_) {
2035 $Sp = shift(@_);
2036 }
2037 my $Start = index(${$CodeRef}, "<$Tag>");
2038 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002040 my $End = index(${$CodeRef}, "</$Tag>");
2041 if($End!=-1)
2042 {
2043 my $TS = length($Tag)+3;
2044 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2045 substr($Content, 0, $TS-1, ""); # cut start tag
2046 substr($Content, -$TS, $TS, ""); # cut end tag
2047 if(not $Sp)
2048 {
2049 $Content=~s/\A\s+//g;
2050 $Content=~s/\s+\Z//g;
2051 }
2052 if(substr($Content, 0, 1) ne "<") {
2053 $Content = xmlSpecChars_R($Content);
2054 }
2055 return $Content;
2056 }
2057 }
2058 return undef;
2059}
2060
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002061sub getInfo($)
2062{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002063 my $DumpPath = $_[0];
2064 return if(not $DumpPath or not -f $DumpPath);
2065
2066 readTUDump($DumpPath);
2067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002068 # processing info
2069 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002070
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002071 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002072 setAnonTypedef_All();
2073 }
2074
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002075 getTypeInfo_All();
2076 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002077 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002078 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002079 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002080
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002081 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002082 %LibInfo = ();
2083 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002084 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002085 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002086 %TemplateDecl = ();
2087 %StdCxxTypedef = ();
2088 %MissedTypedef = ();
2089 %Typedef_Tr = ();
2090 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002091 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002092
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002093 # clean cache
2094 delete($Cache{"getTypeAttr"});
2095 delete($Cache{"getTypeDeclId"});
2096
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002097 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002098 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002099 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002100 }
2101 else
2102 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002103 if($BinaryOnly and not $ExtendedCheck)
2104 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002105 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002106 }
2107 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002108 remove_Unused($Version, "Extended");
2109 }
2110 }
2111
2112 if($CheckInfo)
2113 {
2114 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2115 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2116 }
2117
2118 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2119 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002120 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002121 }
2122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002123 if($Debug) {
2124 # debugMangling($Version);
2125 }
2126}
2127
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002128sub readTUDump($)
2129{
2130 my $DumpPath = $_[0];
2131
2132 open(TU_DUMP, $DumpPath);
2133 local $/ = undef;
2134 my $Content = <TU_DUMP>;
2135 close(TU_DUMP);
2136
2137 unlink($DumpPath);
2138
2139 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002140 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002141
2142 # clean memory
2143 undef $Content;
2144
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002145 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002146
2147 foreach (0 .. $#Lines)
2148 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002149 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002150 { # get a number and attributes of a node
2151 next if(not $NodeType{$2});
2152 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002153 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002154 }
2155
2156 # clean memory
2157 delete($Lines[$_]);
2158 }
2159
2160 # clean memory
2161 undef @Lines;
2162}
2163
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002164sub simplifyConstants()
2165{
2166 foreach my $Constant (keys(%{$Constants{$Version}}))
2167 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002168 if(defined $Constants{$Version}{$Constant}{"Header"})
2169 {
2170 my $Value = $Constants{$Version}{$Constant}{"Value"};
2171 if(defined $EnumConstants{$Version}{$Value}) {
2172 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2173 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002174 }
2175 }
2176}
2177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002178sub simplifyNames()
2179{
2180 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2181 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002182 if($Typedef_Eq{$Version}{$Base}) {
2183 next;
2184 }
2185 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2186 if($#Translations==0)
2187 {
2188 if(length($Translations[0])<=length($Base)) {
2189 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2190 }
2191 }
2192 else
2193 { # select most appropriate
2194 foreach my $Tr (@Translations)
2195 {
2196 if($Base=~/\A\Q$Tr\E/)
2197 {
2198 $Typedef_Eq{$Version}{$Base} = $Tr;
2199 last;
2200 }
2201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002202 }
2203 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002204 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002205 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002206 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002207 if(not $TypeName) {
2208 next;
2209 }
2210 next if(index($TypeName,"<")==-1);# template instances only
2211 if($TypeName=~/>(::\w+)+\Z/)
2212 { # skip unused types
2213 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002214 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002215 foreach my $Base (sort {length($b)<=>length($a)}
2216 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002217 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002218 next if(not $Base);
2219 next if(index($TypeName,$Base)==-1);
2220 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002221 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002222 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002223 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2224 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2225 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002226 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002227 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2228 {
2229 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2230 {
2231 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2232 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002233 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002234 }
2235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002238 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002239 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002240 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2241 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002242 }
2243}
2244
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002245sub setAnonTypedef_All()
2246{
2247 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2248 {
2249 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2250 {
2251 if(isAnon(getNameByInfo($InfoId))) {
2252 $TypedefToAnon{getTypeId($InfoId)} = 1;
2253 }
2254 }
2255 }
2256}
2257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002258sub setTemplateParams_All()
2259{
2260 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2261 {
2262 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2263 setTemplateParams($_);
2264 }
2265 }
2266}
2267
2268sub setTemplateParams($)
2269{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002270 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002271 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002272 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002273 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002274 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002275 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002276 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002277 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002278 setTemplateInstParams($_[0], $TmplInst_Id);
2279 }
2280 }
2281
2282 $BasicTemplate{$Version}{$Tid} = $_[0];
2283
2284 if(my $Prms = getTreeAttr_Prms($_[0]))
2285 {
2286 if(my $Valu = getTreeAttr_Valu($Prms))
2287 {
2288 my $Vector = getTreeVec($Valu);
2289 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2290 {
2291 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2292 {
2293 if(my $Name = getNameByInfo($Val))
2294 {
2295 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2296 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2297 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2298 }
2299 else {
2300 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2301 }
2302 }
2303 }
2304 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002306 }
2307 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002308 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002309 {
2310 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2311 {
2312 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002313 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002314 }
2315 }
2316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002317}
2318
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002319sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002320{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002321 my ($Tmpl, $Inst) = @_;
2322
2323 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002324 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002325 my ($Params_InfoId, $ElemId) = ();
2326 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2327 $Params_InfoId = $1;
2328 }
2329 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2330 $ElemId = $1;
2331 }
2332 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002333 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002334 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2335 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2336 {
2337 my ($PPos, $PTypeId) = ($1, $2);
2338 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2339 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002340 if($PType eq "template_type_parm") {
2341 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002342 }
2343 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002344 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2345 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002346 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002347 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002348 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002349 else
2350 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002351 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002352 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002354 }
2355 }
2356 }
2357}
2358
2359sub getTypeDeclId($)
2360{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002361 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002362 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002363 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2364 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2365 }
2366 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2367 {
2368 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2369 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2370 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002372 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002373 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002374}
2375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002376sub getTypeInfo_All()
2377{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002378 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002379 { # support for GCC < 4.5
2380 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2381 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2382 # FIXME: check GCC versions
2383 addMissedTypes_Pre();
2384 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002386 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002387 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002388 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2389 if($IType=~/_type\Z/ and $IType ne "function_type"
2390 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002391 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002392 }
2393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002394
2395 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002396 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002397 "Name" => "...",
2398 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002399 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002400 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002401 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002402
2403 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002404 { # support for GCC < 4.5
2405 addMissedTypes_Post();
2406 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002407
2408 if($ADD_TMPL_INSTANCES)
2409 {
2410 # templates
2411 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2412 {
2413 if(defined $TemplateMap{$Version}{$Tid}
2414 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2415 {
2416 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2417 {
2418 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2419 {
2420 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2421 {
2422 if(my %MAttr = getTypeAttr($MembTypeId))
2423 {
2424 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2425 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2426 }
2427 }
2428 }
2429 }
2430 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2431 {
2432 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2433 {
2434 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2435
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002436 if($NBid ne $Bid
2437 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002438 {
2439 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2440 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2441 }
2442 }
2443 }
2444 }
2445 }
2446 }
2447}
2448
2449sub createType($$)
2450{
2451 my ($Attr, $LibVersion) = @_;
2452 my $NewId = ++$MAX_ID;
2453
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002454 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002455 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002456 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002457
2458 return "$NewId";
2459}
2460
2461sub instType($$$)
2462{ # create template instances
2463 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002464
2465 if(not $TypeInfo{$LibVersion}{$Tid}) {
2466 return undef;
2467 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002468 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2469
2470 foreach my $Key (sort keys(%{$Map}))
2471 {
2472 if(my $Val = $Map->{$Key})
2473 {
2474 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2475
2476 if(defined $Attr->{"NameSpace"}) {
2477 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2478 }
2479 foreach (keys(%{$Attr->{"TParam"}})) {
2480 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2481 }
2482 }
2483 else
2484 { # remove absent
2485 # _Traits, etc.
2486 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002487 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002488 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2489 }
2490 foreach (keys(%{$Attr->{"TParam"}}))
2491 {
2492 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2493 delete($Attr->{"TParam"}{$_});
2494 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002495 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002496 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2497 }
2498 }
2499 }
2500 }
2501
2502 my $Tmpl = 0;
2503
2504 if(defined $Attr->{"TParam"})
2505 {
2506 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2507 {
2508 my $PName = $Attr->{"TParam"}{$_}{"name"};
2509
2510 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2511 {
2512 my %Base = get_BaseType($PTid, $LibVersion);
2513
2514 if($Base{"Type"} eq "TemplateParam"
2515 or defined $Base{"Template"})
2516 {
2517 $Tmpl = 1;
2518 last
2519 }
2520 }
2521 }
2522 }
2523
2524 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2525 return "$Id";
2526 }
2527 else
2528 {
2529 if(not $Tmpl) {
2530 delete($Attr->{"Template"});
2531 }
2532
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002533 my $New = createType($Attr, $LibVersion);
2534
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 my %EMap = ();
2536 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2537 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2538 }
2539 foreach (keys(%{$Map})) {
2540 $EMap{$_} = $Map->{$_};
2541 }
2542
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002543 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2544 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002545 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002546 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002547 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002548 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002549 {
2550 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2551
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002552 if($NBid ne $Bid
2553 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002554 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002555 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2556 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002557 }
2558 }
2559 }
2560
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002561 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002562 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002563 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2564 {
2565 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2566 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2567 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002568 }
2569 }
2570
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002571 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002572 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002573 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2574 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002575 }
2576 }
2577
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002578 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2579 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002580 }
2581
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002582 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002583 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002584}
2585
2586sub addMissedTypes_Pre()
2587{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002588 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002589 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2590 { # detecting missed typedefs
2591 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2592 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002593 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002594 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002595 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 if($TypeType eq "Unknown")
2597 { # template_type_parm
2598 next;
2599 }
2600 my $TypeDeclId = getTypeDeclId($TypeId);
2601 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2602 my $TypedefName = getNameByInfo($MissedTDid);
2603 next if(not $TypedefName);
2604 next if($TypedefName eq "__float80");
2605 next if(isAnon($TypedefName));
2606 if(not $TypeDeclId
2607 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002608 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002609 }
2610 }
2611 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002612 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002613 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002615 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 next;
2618 }
2619 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002621 if(not $TypedefName) {
2622 next;
2623 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002624 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 my %MissedInfo = ( # typedef info
2626 "Name" => $TypedefName,
2627 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002628 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002630 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631 my ($H, $L) = getLocation($MissedTDid);
2632 $MissedInfo{"Header"} = $H;
2633 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002634 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635 { # other types
2636 next;
2637 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002638 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002640 next;
2641 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002642 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002643 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002644 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002645 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002646 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002647 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002648 next;
2649 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002650 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002651 next;
2652 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002653 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002655 next;
2656 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002657 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002659 next;
2660 }
2661 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002662
2663 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002665 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002667 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002668 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002670
2671 # add missed & remove other
2672 $TypeInfo{$Version} = \%AddTypes;
2673 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002674}
2675
2676sub addMissedTypes_Post()
2677{
2678 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2679 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002680 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2681 {
2682 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2683 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2684 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2685 }
2686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 }
2688}
2689
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002690sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002691{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002692 my $TypeId = $_[0];
2693 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2694 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002695 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002696 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698}
2699
2700sub getArraySize($$)
2701{
2702 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002703 if(my $Size = getSize($TypeId))
2704 {
2705 my $Elems = $Size/$BYTE_SIZE;
2706 while($BaseName=~s/\s*\[(\d+)\]//) {
2707 $Elems/=$1;
2708 }
2709 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2710 {
2711 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2712 $Elems/=$BasicSize;
2713 }
2714 }
2715 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718}
2719
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002720sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002721{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002722 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002723 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002724 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2725 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002726 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002727 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2728 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2729 if(not $NodeType)
2730 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002731 return ();
2732 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002733 if($NodeType eq "tree_vec")
2734 {
2735 if($Pos!=$#Positions)
2736 { # select last vector of parameters ( ns<P1>::type<P2> )
2737 next;
2738 }
2739 }
2740 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2741 foreach my $P (@Params)
2742 {
2743 if($P eq "") {
2744 return ();
2745 }
2746 elsif($P ne "\@skip\@") {
2747 @TmplParams = (@TmplParams, $P);
2748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 }
2750 }
2751 return @TmplParams;
2752}
2753
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002754sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002756 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002757 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002758 if(defined $TypeInfo{$Version}{$TypeId}
2759 and $TypeInfo{$Version}{$TypeId}{"Name"})
2760 { # already created
2761 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002762 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002763 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2764 { # incomplete type
2765 return ();
2766 }
2767 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2768
2769 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002771
2772 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2773 {
2774 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2775 {
2776 if($Info=~/qual[ ]*:/)
2777 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002778 my $NewId = ++$MAX_ID;
2779
2780 $MissedBase{$Version}{$TypeId} = "$NewId";
2781 $MissedBase_R{$Version}{$NewId} = $TypeId;
2782 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2783 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002784 }
2785 }
2786 $TypeAttr{"Type"} = "Typedef";
2787 }
2788 else {
2789 $TypeAttr{"Type"} = getTypeType($TypeId);
2790 }
2791
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002792 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2793 {
2794 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2795 { # local code
2796 return ();
2797 }
2798 }
2799
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002800 if($TypeAttr{"Type"} eq "Unknown") {
2801 return ();
2802 }
2803 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2804 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002805 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002806 if(my $TName = $TypeAttr{"Name"})
2807 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002808 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002809 $TName_Tid{$Version}{$TName} = $TypeId;
2810 return %TypeAttr;
2811 }
2812 else {
2813 return ();
2814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002815 }
2816 elsif($TypeAttr{"Type"} eq "Array")
2817 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002818 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2819 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002820 return ();
2821 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002822 if(my $Algn = getAlgn($TypeId)) {
2823 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2824 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002825 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002828 if(not $BTAttr{"Name"}) {
2829 return ();
2830 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002831 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002832 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002833 if(my $Size = getSize($TypeId)) {
2834 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2835 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002836 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002837 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2838 }
2839 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002840 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002842 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002843 else
2844 {
2845 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002846 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002847 $TypeAttr{"Name"} = $1."[]".$2;
2848 }
2849 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002850 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002852 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002853 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002854 if($BTAttr{"Header"}) {
2855 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002856 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002857 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002858 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2859 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002860 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002861 return ();
2862 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002863 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002864 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002865 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002866 if($TypeAttr{"Name"})
2867 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002868 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002869
2870 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2871 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002872 { # NOTE: register only one int: with built-in decl
2873 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2874 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2875 }
2876 }
2877 return %TypeAttr;
2878 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002879 else {
2880 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002882 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002883 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2884 {
2885 %TypeAttr = getTrivialTypeAttr($TypeId);
2886 if($TypeAttr{"Name"})
2887 {
2888 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2889 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2890 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2891 }
2892 return %TypeAttr;
2893 }
2894 else {
2895 return ();
2896 }
2897 }
2898 elsif($TypeAttr{"Type"} eq "SizeOf")
2899 {
2900 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2901 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2902 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2903 if($TypeAttr{"Name"})
2904 {
2905 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2906 return %TypeAttr;
2907 }
2908 else {
2909 return ();
2910 }
2911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002912 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002913 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002914 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2915 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002916 return ();
2917 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002918 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002919 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002920 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002921 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002922 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002923 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002924 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002926 }
2927 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002928 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002929 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002930 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002931 return ();
2932 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002933 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002934 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002935 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002936 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002937 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002938 }
2939 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002940 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002941 {
2942 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002943 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002944 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002945 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002946 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2947 }
2948 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002949 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002950 }
2951 }
2952 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002953 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002954 }
2955 if($TypeAttr{"Type"} eq "Typedef")
2956 {
2957 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002958
2959 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2960 return ();
2961 }
2962
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002963 if(isAnon($TypeAttr{"Name"}))
2964 { # anon typedef to anon type: ._N
2965 return ();
2966 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002967
2968 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2969 { # artificial typedef of "struct X" to "X"
2970 $TypeAttr{"Artificial"} = 1;
2971 }
2972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002973 if(my $NS = getNameSpace($TypeDeclId))
2974 {
2975 my $TypeName = $TypeAttr{"Name"};
2976 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2977 { # "some_type" is the typedef to "struct some_type" in C++
2978 if($3) {
2979 $TypeAttr{"Name"} = $3."::".$TypeName;
2980 }
2981 }
2982 else
2983 {
2984 $TypeAttr{"NameSpace"} = $NS;
2985 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002986
2987 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2988 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2989 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002990 if($BTAttr{"NameSpace"}
2991 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002992 { # types like "std::fpos<__mbstate_t>" are
2993 # not covered by typedefs in the TU dump
2994 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002995 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2996 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002997 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002998 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002999 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003000 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003002 }
3003 }
3004 }
3005 }
3006 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003007 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003008 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003009 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003010 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3011 { # typedef int*const TYPEDEF; // first
3012 # int foo(TYPEDEF p); // const is optimized out
3013 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3014 if($BTAttr{"Name"}=~/</)
3015 {
3016 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3017 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3018 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003019 }
3020 }
3021 }
3022 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3023 }
3024 if(not $TypeAttr{"Size"})
3025 {
3026 if($TypeAttr{"Type"} eq "Pointer") {
3027 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3028 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003029 elsif($BTAttr{"Size"}) {
3030 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003031 }
3032 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003033 if(my $Algn = getAlgn($TypeId)) {
3034 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3035 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003036 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003037 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3038 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003040 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003041 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003042 { # typedef to "class Class"
3043 # should not be registered in TName_Tid
3044 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3045 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 }
3048 return %TypeAttr;
3049 }
3050}
3051
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003052sub getTreeVec($)
3053{
3054 my %Vector = ();
3055 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3056 {
3057 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3058 { # string length is N-1 because of the null terminator
3059 $Vector{$1} = $2;
3060 }
3061 }
3062 return \%Vector;
3063}
3064
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065sub get_TemplateParam($$)
3066{
3067 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003068 return () if(not $Type_Id);
3069 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3070 return () if(not $NodeType);
3071 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003072 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003073 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003074 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003075 my $Num = getNodeIntCst($Type_Id);
3076 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003077 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 }
3079 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003080 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003081 }
3082 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003083 elsif($NodeType eq "string_cst") {
3084 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003086 elsif($NodeType eq "tree_vec")
3087 {
3088 my $Vector = getTreeVec($Type_Id);
3089 my @Params = ();
3090 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3091 {
3092 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3093 push(@Params, $P2);
3094 }
3095 }
3096 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003098 elsif($NodeType eq "parm_decl")
3099 {
3100 (getNameByInfo($Type_Id));
3101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 else
3103 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003104 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003105 my $PName = $ParamAttr{"Name"};
3106 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003108 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003109 if($PName=~/\>/)
3110 {
3111 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003112 $PName = $Cover;
3113 }
3114 }
3115 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003116 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003117 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3118 # template<typename _Key, typename _Compare = std::less<_Key>
3119 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3120 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3121 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3122 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003123 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003125 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003126 }
3127}
3128
3129sub cover_stdcxx_typedef($)
3130{
3131 my $TypeName = $_[0];
3132 if(my @Covers = sort {length($a)<=>length($b)}
3133 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3134 { # take the shortest typedef
3135 # FIXME: there may be more than
3136 # one typedefs to the same type
3137 return $Covers[0];
3138 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003139 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003140 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3141 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3142 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003143 if(my $Cover = $Covers[0])
3144 {
3145 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3146 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003148 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003149 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003150}
3151
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003152sub getNodeIntCst($)
3153{
3154 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003155 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156 if($EnumMembName_Id{$Version}{$CstId}) {
3157 return $EnumMembName_Id{$Version}{$CstId};
3158 }
3159 elsif((my $Value = getTreeValue($CstId)) ne "")
3160 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003161 if($Value eq "0")
3162 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003163 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003164 return "false";
3165 }
3166 else {
3167 return "0";
3168 }
3169 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003170 elsif($Value eq "1")
3171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003172 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173 return "true";
3174 }
3175 else {
3176 return "1";
3177 }
3178 }
3179 else {
3180 return $Value;
3181 }
3182 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003183 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003184}
3185
3186sub getNodeStrCst($)
3187{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003188 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3189 {
3190 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003191 {
3192 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3193 { # string length is N-1 because of the null terminator
3194 return substr($1, 0, $2-1);
3195 }
3196 else
3197 { # identifier_node
3198 return substr($1, 0, $2);
3199 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003201 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003202 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003203}
3204
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003205sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003206{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003207 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003208 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3209 if($Type eq "FieldPtr") {
3210 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3211 }
3212 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3213 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003214 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003215 if($Type eq "MethodPtr")
3216 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003217 if(my $Size = getSize($TypeId))
3218 {
3219 $Size/=$BYTE_SIZE;
3220 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003222 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003223 if(my $Algn = getAlgn($TypeId)) {
3224 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 # Return
3227 if($Type eq "FieldPtr")
3228 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003229 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003230 if($ReturnAttr{"Name"}) {
3231 $MemPtrName .= $ReturnAttr{"Name"};
3232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003233 $TypeAttr{"Return"} = $PtrId;
3234 }
3235 else
3236 {
3237 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3238 {
3239 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003240 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3241 if(not $ReturnAttr{"Name"})
3242 { # templates
3243 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003244 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003245 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003246 $TypeAttr{"Return"} = $ReturnTypeId;
3247 }
3248 }
3249 # Class
3250 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3251 {
3252 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003253 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 if($Class{"Name"}) {
3255 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3256 }
3257 else {
3258 $MemPtrName .= " (*)";
3259 }
3260 }
3261 else {
3262 $MemPtrName .= " (*)";
3263 }
3264 # Parameters
3265 if($Type eq "FuncPtr"
3266 or $Type eq "MethodPtr")
3267 {
3268 my @ParamTypeName = ();
3269 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3270 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003271 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003272 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003273 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003275 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3276 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003277 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003278 my $PTypeId = $1;
3279 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003280 if(not $ParamAttr{"Name"})
3281 { # templates (template_type_parm), etc.
3282 return ();
3283 }
3284 if($ParamAttr{"Name"} eq "void") {
3285 last;
3286 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003287 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003288 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003289 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003290 push(@ParamTypeName, $ParamAttr{"Name"});
3291 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003292 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3293 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003294 }
3295 else {
3296 last;
3297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003299 else {
3300 last;
3301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003302 }
3303 }
3304 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3305 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003306 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307 return %TypeAttr;
3308}
3309
3310sub getTreeTypeName($)
3311{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003312 my $TypeId = $_[0];
3313 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003314 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003315 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003317 if(my $Name = getNameByInfo($TypeId))
3318 { # bit_size_type
3319 return $Name;
3320 }
3321 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003322 return "unsigned int";
3323 }
3324 else {
3325 return "int";
3326 }
3327 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003328 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003329 return getNameByInfo($1);
3330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003331 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003332 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003333}
3334
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003335sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003336{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003337 my $Ptd = pointTo($_[0]);
3338 return 0 if(not $Ptd);
3339 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003340 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003341 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3342 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003343 }
3344 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003345 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3346 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003347 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003348 if($InfoT1 eq "pointer_type"
3349 and $InfoT2 eq "function_type") {
3350 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003351 }
3352 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003353 return 0;
3354}
3355
3356sub isMethodPtr($)
3357{
3358 my $Ptd = pointTo($_[0]);
3359 return 0 if(not $Ptd);
3360 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3361 {
3362 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3363 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3364 and $Info=~/ ptrmem /) {
3365 return 1;
3366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003367 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003368 return 0;
3369}
3370
3371sub isFieldPtr($)
3372{
3373 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3374 {
3375 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3376 and $Info=~/ ptrmem /) {
3377 return 1;
3378 }
3379 }
3380 return 0;
3381}
3382
3383sub pointTo($)
3384{
3385 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3386 {
3387 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3388 return $1;
3389 }
3390 }
3391 return "";
3392}
3393
3394sub getTypeTypeByTypeId($)
3395{
3396 my $TypeId = $_[0];
3397 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3398 {
3399 my $NType = $NodeType{$TType};
3400 if($NType eq "Intrinsic") {
3401 return $NType;
3402 }
3403 elsif(isFuncPtr($TypeId)) {
3404 return "FuncPtr";
3405 }
3406 elsif(isMethodPtr($TypeId)) {
3407 return "MethodPtr";
3408 }
3409 elsif(isFieldPtr($TypeId)) {
3410 return "FieldPtr";
3411 }
3412 elsif($NType ne "Other") {
3413 return $NType;
3414 }
3415 }
3416 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003417}
3418
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003419my %UnQual = (
3420 "r"=>"restrict",
3421 "v"=>"volatile",
3422 "c"=>"const",
3423 "cv"=>"const volatile"
3424);
3425
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003426sub getQual($)
3427{
3428 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003429 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3430 {
3431 my ($Qual, $To) = ();
3432 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3433 $Qual = $UnQual{$1};
3434 }
3435 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3436 $To = $1;
3437 }
3438 if($Qual and $To) {
3439 return ($Qual, $To);
3440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003441 }
3442 return ();
3443}
3444
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003445sub getQualType($)
3446{
3447 if($_[0] eq "const volatile") {
3448 return "ConstVolatile";
3449 }
3450 return ucfirst($_[0]);
3451}
3452
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003453sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003455 my $TypeId = $_[0];
3456 my $TypeDeclId = getTypeDeclId($TypeId);
3457 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003458 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003459 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3460 return "Typedef";
3461 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003462 }
3463 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3464 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003465 if(($Qual or $To) and $TypeDeclId
3466 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003467 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003468 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470 elsif(not $MissedBase_R{$Version}{$TypeId}
3471 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003472 return "Typedef";
3473 }
3474 elsif($Qual)
3475 { # qualified types
3476 return getQualType($Qual);
3477 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003478
3479 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3480 { # typedef struct { ... } name
3481 $TypeTypedef{$Version}{$TypeId} = $1;
3482 }
3483
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003484 my $TypeType = getTypeTypeByTypeId($TypeId);
3485 if($TypeType eq "Struct")
3486 {
3487 if($TypeDeclId
3488 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3489 return "Template";
3490 }
3491 }
3492 return $TypeType;
3493}
3494
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003495sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003496{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003497 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003498 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003499 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3500 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3501 return 0;
3502 }
3503 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3504 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003505 if(my $TDid = getTypeDeclId($_[0]))
3506 {
3507 if(getTypeId($TDid) eq $_[0]
3508 and getNameByInfo($TDid))
3509 {
3510 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3511 return $1;
3512 }
3513 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003514 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 }
3516 }
3517 return 0;
3518}
3519
3520sub selectBaseType($)
3521{
3522 my $TypeId = $_[0];
3523 if(defined $MissedTypedef{$Version}{$TypeId})
3524 { # add missed typedefs
3525 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3526 return ($TypeId, "");
3527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003529 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3530 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003531
3532 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3533 my $MB = $MissedBase{$Version}{$TypeId};
3534
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003535 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003536 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003537 and (getTypeId($1) ne $TypeId)
3538 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003539 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003540 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003542 elsif($MB)
3543 { # add base
3544 return ($MB, "");
3545 }
3546 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003547 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003550 elsif($Qual or $To)
3551 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003553 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003554 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003555 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003556 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003557 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003559 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003561 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003562 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003565 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003566 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003567 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003568 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003569 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003571 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003572
3573 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574}
3575
3576sub getSymbolInfo_All()
3577{
3578 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3579 { # reverse order
3580 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003581 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 }
3583 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003584
3585 if($ADD_TMPL_INSTANCES)
3586 {
3587 # templates
3588 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3589 {
3590 my %Map = ();
3591
3592 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3593 {
3594 if(defined $TemplateMap{$Version}{$ClassId})
3595 {
3596 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3597 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3598 }
3599 }
3600 }
3601
3602 if(defined $TemplateMap{$Version}{$Sid})
3603 {
3604 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3605 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3606 }
3607 }
3608
3609 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3610 {
3611 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3612 {
3613 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3614 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3615 }
3616 }
3617 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3618 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3619 }
3620 }
3621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003622}
3623
3624sub getVarInfo_All()
3625{
3626 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3627 { # reverse order
3628 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003629 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003630 }
3631 }
3632}
3633
3634sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003635 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003636}
3637
3638sub getVarInfo($)
3639{
3640 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003641 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003642 {
3643 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3644 if($NSInfoType and $NSInfoType eq "function_decl") {
3645 return;
3646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003647 }
3648 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3649 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3650 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3651 delete($SymbolInfo{$Version}{$InfoId});
3652 return;
3653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003654 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003655 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003656 delete($SymbolInfo{$Version}{$InfoId});
3657 return;
3658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003659 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3660 delete($SymbolInfo{$Version}{$InfoId});
3661 return;
3662 }
3663 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003664 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3665 {
3666 if($OSgroup eq "windows")
3667 { # cut the offset
3668 $MnglName=~s/\@\d+\Z//g;
3669 }
3670 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003672 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003673 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003674 { # validate mangled name
3675 delete($SymbolInfo{$Version}{$InfoId});
3676 return;
3677 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003678 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003679 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003680 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003681 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003682 }
3683 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3684 { # non-public global data
3685 delete($SymbolInfo{$Version}{$InfoId});
3686 return;
3687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003689 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003690 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003691 if(not defined $TypeInfo{$Version}{$Rid}
3692 or not $TypeInfo{$Version}{$Rid}{"Name"})
3693 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003694 delete($SymbolInfo{$Version}{$InfoId});
3695 return;
3696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003697 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3698 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003699 if(defined $Val) {
3700 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003702 }
3703 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003704 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3705 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003706 if(not defined $TypeInfo{$Version}{$ClassId}
3707 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3708 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003709 delete($SymbolInfo{$Version}{$InfoId});
3710 return;
3711 }
3712 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003713 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3714 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003715 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003716 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003717 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003718 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003719 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003720 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003721 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003722 if(not $CheckHeadersOnly)
3723 {
3724 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3725 {
3726 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3727 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3728 {
3729 if(link_symbol($ShortName, $Version, "-Deps"))
3730 { # "const" global data is mangled as _ZL... in the TU dump
3731 # but not mangled when compiling a C shared library
3732 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3733 }
3734 }
3735 }
3736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003737 if($COMMON_LANGUAGE{$Version} eq "C++")
3738 {
3739 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3740 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003741 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3743 }
3744 }
3745 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3746 { # try to mangle symbol (link with libraries)
3747 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3748 }
3749 if($OStarget eq "windows")
3750 {
3751 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3752 { # link MS C++ symbols from library with GCC symbols from headers
3753 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3754 }
3755 }
3756 }
3757 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3758 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003760 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3761 {
3762 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3763 { # non-target symbols
3764 delete($SymbolInfo{$Version}{$InfoId});
3765 return;
3766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003767 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003768 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3769 {
3770 if(defined $MissedTypedef{$Version}{$Rid})
3771 {
3772 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3773 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3774 }
3775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003776 }
3777 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003778 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003779 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3780 }
3781 if($ShortName=~/\A(_Z|\?)/) {
3782 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3783 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003784
3785 if($ExtraDump) {
3786 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003788}
3789
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003790sub isConstType($$)
3791{
3792 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003793 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003794 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003795 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003796 }
3797 return ($Base{"Type"} eq "Const");
3798}
3799
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003800sub getTrivialName($$)
3801{
3802 my ($TypeInfoId, $TypeId) = @_;
3803 my %TypeAttr = ();
3804 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3805 if(not $TypeAttr{"Name"}) {
3806 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3807 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003808 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003809 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003810 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003811 if(isAnon($TypeAttr{"Name"}))
3812 {
3813 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003814 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003815 { # searching for a first not anon scope
3816 if($NSId eq $NameSpaceId) {
3817 last;
3818 }
3819 else
3820 {
3821 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3822 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003823 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003824 last;
3825 }
3826 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003827 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003828 }
3829 }
3830 else
3831 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003832 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003833 {
3834 if($NameSpaceId ne $TypeId) {
3835 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 }
3838 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003839 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003840 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3841 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003842 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003844 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003845 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003846 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003847 if($TypeAttr{"NameSpace"}) {
3848 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003850 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003851 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3852 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003853 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003854 if(my @TParams = getTParams($TypeId, "Type")) {
3855 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3856 }
3857 else {
3858 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003860 }
3861 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3862}
3863
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003864sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003865{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003866 my $TypeId = $_[0];
3867 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003868
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003869 my %TypeAttr = ();
3870
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003871 if($TemplateDecl{$Version}{$TypeId})
3872 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003873 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003874 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003875
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003876 setTypeAccess($TypeId, \%TypeAttr);
3877 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3878 if(isBuiltIn($TypeAttr{"Header"}))
3879 {
3880 delete($TypeAttr{"Header"});
3881 delete($TypeAttr{"Line"});
3882 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003883
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003884 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003885 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3886 if(not $TypeAttr{"Name"}) {
3887 return ();
3888 }
3889 if(not $TypeAttr{"NameSpace"}) {
3890 delete($TypeAttr{"NameSpace"});
3891 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003892
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003893 if($TypeAttr{"Type"} eq "Intrinsic")
3894 {
3895 if(defined $TypeAttr{"Header"})
3896 {
3897 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3898 { # support for SUSE 11.2
3899 # integer_type has srcp dump{1-2}.i
3900 delete($TypeAttr{"Header"});
3901 }
3902 }
3903 }
3904
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003905 my $Tmpl = undef;
3906
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003907 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003908 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003909 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3910
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003911 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003912 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003913 foreach my $Pos (0 .. $#TParams)
3914 {
3915 my $Val = $TParams[$Pos];
3916 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3917
3918 if(not defined $TypeAttr{"Template"})
3919 {
3920 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3921
3922 if($Base{"Type"} eq "TemplateParam"
3923 or defined $Base{"Template"}) {
3924 $TypeAttr{"Template"} = 1;
3925 }
3926 }
3927
3928 if($Tmpl)
3929 {
3930 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3931 {
3932 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3933
3934 if($Val eq $Arg) {
3935 $TypeAttr{"Template"} = 1;
3936 }
3937 }
3938 }
3939 }
3940
3941 if($Tmpl)
3942 {
3943 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3944 {
3945 if($Pos>$#TParams)
3946 {
3947 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3948 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3949 }
3950 }
3951 }
3952 }
3953
3954 if($ADD_TMPL_INSTANCES)
3955 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003956 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003957 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003958 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003959 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003960 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003961 {
3962 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3963 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3964 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003965 }
3966 if(not getTreeAttr_Binf($TypeId))
3967 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003968 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3969 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3970 }
3971 }
3972 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003973 }
3974 }
3975 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003976
3977 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3978
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003979 if(my $Size = getSize($TypeId))
3980 {
3981 $Size = $Size/$BYTE_SIZE;
3982 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003983 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003984 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003985 {
3986 if($ExtraDump)
3987 {
3988 if(not defined $TypeAttr{"Memb"}
3989 and not $Tmpl)
3990 { # declaration only
3991 $TypeAttr{"Forward"} = 1;
3992 }
3993 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003994 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003996 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003997 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003998 {
3999 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004000 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004001 }
4002 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004003 or $TypeAttr{"Type"} eq "Class")
4004 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004005 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004006 if($Skip) {
4007 return ();
4008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004009 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004010 if(my $Algn = getAlgn($TypeId)) {
4011 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004013 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004014
4015 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4016 {
4017 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004018 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004019 {
4020 if(not isAnon($TypeAttr{"Name"})) {
4021 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4022 }
4023 }
4024 }
4025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004026 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004027 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4028 {
4029 my @Entries = split(/\n/, $VTable);
4030 foreach (1 .. $#Entries)
4031 {
4032 my $Entry = $Entries[$_];
4033 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004034 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004035 }
4036 }
4037 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004038
4039 if($TypeAttr{"Type"} eq "Enum")
4040 {
4041 if(not $TypeAttr{"NameSpace"})
4042 {
4043 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4044 {
4045 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004046 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004047 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004048 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004049 "Header"=>$TypeAttr{"Header"}
4050 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004051 if(isAnon($TypeAttr{"Name"}))
4052 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004053 if($ExtraDump
4054 or is_target_header($TypeAttr{"Header"}, $Version))
4055 {
4056 %{$Constants{$Version}{$MName}} = (
4057 "Value" => $MVal,
4058 "Header" => $TypeAttr{"Header"}
4059 );
4060 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004061 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004062 }
4063 }
4064 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004065 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004066 {
4067 if(defined $TypedefToAnon{$TypeId}) {
4068 $TypeAttr{"AnonTypedef"} = 1;
4069 }
4070 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004071
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004072 return %TypeAttr;
4073}
4074
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004075sub simplifyVTable($)
4076{
4077 my $Content = $_[0];
4078 if($Content=~s/ \[with (.+)]//)
4079 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4080 if(my @Elems = separate_Params($1, 0, 0))
4081 {
4082 foreach my $Elem (@Elems)
4083 {
4084 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4085 {
4086 my ($Arg, $Val) = ($1, $2);
4087
4088 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4089 $Content=~s/,\s*$Arg\b//g;
4090 }
4091 else {
4092 $Content=~s/\b$Arg\b/$Val/g;
4093 }
4094 }
4095 }
4096 }
4097 }
4098
4099 return $Content;
4100}
4101
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004102sub detect_lang($)
4103{
4104 my $TypeId = $_[0];
4105 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004106 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004107 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004108 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4109 }
4110 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004111 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004112 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004113 while($Fncs)
4114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004115 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 return 1;
4117 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004118 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 }
4120 }
4121 return 0;
4122}
4123
4124sub setSpec($$)
4125{
4126 my ($TypeId, $TypeAttr) = @_;
4127 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4128 if($Info=~/\s+spec\s+/) {
4129 $TypeAttr->{"Spec"} = 1;
4130 }
4131}
4132
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004133sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004135 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004136 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004137 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004138 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004139 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004140 my $Pos = 0;
4141 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4142 {
4143 my ($Access, $BInfoId) = ($1, $2);
4144 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004145
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004146 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004147 { # class A<N>:public A<N-1>
4148 next;
4149 }
4150
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004151 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4152 if(not $CType or $CType eq "template_type_parm"
4153 or $CType eq "typename_type")
4154 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004155 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004157 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004158 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4160 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004161 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004162 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4163 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004164 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004165 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004166 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004167 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4168 }
4169 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004170 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004171 }
4172 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004173 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004174}
4175
4176sub getBinfClassId($)
4177{
4178 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004179 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4180 return $1;
4181 }
4182
4183 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004184}
4185
4186sub unmangledFormat($$)
4187{
4188 my ($Name, $LibVersion) = @_;
4189 $Name = uncover_typedefs($Name, $LibVersion);
4190 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4191 $Name=~s/\(\w+\)(\d)/$1/;
4192 return $Name;
4193}
4194
4195sub modelUnmangled($$)
4196{
4197 my ($InfoId, $Compiler) = @_;
4198 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4199 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4200 }
4201 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4202 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4203 $PureSignature = "~".$PureSignature;
4204 }
4205 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4206 {
4207 my (@Params, @ParamTypes) = ();
4208 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4209 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4210 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4211 }
4212 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4213 { # checking parameters
4214 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004215 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004216 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004217 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004218
4219 if($PName eq "this"
4220 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4221 {
4222 next;
4223 }
4224
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004225 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004227 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004228 }
4229 @ParamTypes = (@ParamTypes, $PTName);
4230 }
4231 if(@ParamTypes) {
4232 $PureSignature .= "(".join(", ", @ParamTypes).")";
4233 }
4234 else
4235 {
4236 if($Compiler eq "MSVC")
4237 {
4238 $PureSignature .= "(void)";
4239 }
4240 else
4241 { # GCC
4242 $PureSignature .= "()";
4243 }
4244 }
4245 $PureSignature = delete_keywords($PureSignature);
4246 }
4247 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4248 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004249 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004250 $PureSignature = $ClassName."::".$PureSignature;
4251 }
4252 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4253 $PureSignature = $NS."::".$PureSignature;
4254 }
4255 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4256 $PureSignature .= " const";
4257 }
4258 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4259 $PureSignature .= " volatile";
4260 }
4261 my $ShowReturn = 0;
4262 if($Compiler eq "MSVC"
4263 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4264 {
4265 $ShowReturn=1;
4266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004267 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4268 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004269 {
4270 $ShowReturn=1;
4271 }
4272 if($ShowReturn)
4273 { # mangled names for template function specializations include return value
4274 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4275 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004276 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004277 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4278 $PureSignature = $ReturnName." ".$PureSignature;
4279 }
4280 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004281 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004282}
4283
4284sub mangle_symbol($$$)
4285{ # mangling for simple methods
4286 # see gcc-4.6.0/gcc/cp/mangle.c
4287 my ($InfoId, $LibVersion, $Compiler) = @_;
4288 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4289 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4290 }
4291 my $Mangled = "";
4292 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004293 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004294 }
4295 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004296 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004297 }
4298 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4299}
4300
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004301sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004302{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004303 my ($InfoId, $LibVersion) = @_;
4304 return "";
4305}
4306
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004307sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004308{ # see gcc-4.6.0/gcc/cp/mangle.c
4309 my ($InfoId, $LibVersion) = @_;
4310 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004311 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004312 my %Repl = ();# SN_ replacements
4313 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4314 {
4315 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4316 if($MangledClass!~/\AN/) {
4317 $MangledClass = "N".$MangledClass;
4318 }
4319 else {
4320 $MangledClass=~s/E\Z//;
4321 }
4322 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4323 $MangledClass=~s/\AN/NV/;
4324 }
4325 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4326 $MangledClass=~s/\AN/NK/;
4327 }
4328 $Mangled .= $MangledClass;
4329 }
4330 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4331 { # mangled by name due to the absence of structured info
4332 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4333 if($MangledNS!~/\AN/) {
4334 $MangledNS = "N".$MangledNS;
4335 }
4336 else {
4337 $MangledNS=~s/E\Z//;
4338 }
4339 $Mangled .= $MangledNS;
4340 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004341 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004342 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004343 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004344 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004345 foreach (@TPos) {
4346 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4347 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004348 }
4349 elsif($TmplParams)
4350 { # remangling mode
4351 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004352 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004353 }
4354 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4355 $Mangled .= "C1";
4356 }
4357 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4358 $Mangled .= "D0";
4359 }
4360 elsif($ShortName)
4361 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004362 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4363 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004364 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004365 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004366 { # "const" global data is mangled as _ZL...
4367 $Mangled .= "L";
4368 }
4369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004370 if($ShortName=~/\Aoperator(\W.*)\Z/)
4371 {
4372 my $Op = $1;
4373 $Op=~s/\A[ ]+//g;
4374 if(my $OpMngl = $OperatorMangling{$Op}) {
4375 $Mangled .= $OpMngl;
4376 }
4377 else { # conversion operator
4378 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4379 }
4380 }
4381 else {
4382 $Mangled .= length($ShortName).$ShortName;
4383 }
4384 if(@TParams)
4385 { # templates
4386 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004387 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004388 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4389 }
4390 $Mangled .= "E";
4391 }
4392 if(not $ClassId and @TParams) {
4393 add_substitution($ShortName, \%Repl, 0);
4394 }
4395 }
4396 if($ClassId or $NameSpace) {
4397 $Mangled .= "E";
4398 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004399 if(@TParams)
4400 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004401 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004402 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4403 }
4404 }
4405 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4406 {
4407 my @Params = ();
4408 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4409 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4410 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4411 }
4412 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4413 { # checking parameters
4414 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4415 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4416 }
4417 if(not @Params) {
4418 $Mangled .= "v";
4419 }
4420 }
4421 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4422 $Mangled = write_stdcxx_substitution($Mangled);
4423 if($Mangled eq "_Z") {
4424 return "";
4425 }
4426 return $Mangled;
4427}
4428
4429sub correct_incharge($$$)
4430{
4431 my ($InfoId, $LibVersion, $Mangled) = @_;
4432 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4433 {
4434 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004435 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004436 }
4437 }
4438 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4439 {
4440 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004441 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004442 }
4443 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004444 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004445 }
4446 }
4447 return $Mangled;
4448}
4449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004450sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004451{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004452 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004453 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004454 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004455 return $Name;
4456 }
4457 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004458 while(my $CPos = find_center($TParams, "<"))
4459 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004460 $TParams = substr($TParams, $CPos);
4461 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004462 if($TParams=~s/\A<(.+)>\Z/$1/) {
4463 $Name=~s/<\Q$TParams\E>\Z//;
4464 }
4465 else
4466 { # error
4467 $TParams = "";
4468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004469 return ($Name, $TParams);
4470}
4471
4472sub get_sub_ns($)
4473{
4474 my $Name = $_[0];
4475 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004476 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004477 {
4478 push(@NS, substr($Name, 0, $CPos));
4479 $Name = substr($Name, $CPos);
4480 $Name=~s/\A:://;
4481 }
4482 return (join("::", @NS), $Name);
4483}
4484
4485sub mangle_ns($$$)
4486{
4487 my ($Name, $LibVersion, $Repl) = @_;
4488 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4489 {
4490 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4491 $Mangled=~s/\AN(.+)E\Z/$1/;
4492 return $Mangled;
4493
4494 }
4495 else
4496 {
4497 my ($MangledNS, $SubNS) = ("", "");
4498 ($SubNS, $Name) = get_sub_ns($Name);
4499 if($SubNS) {
4500 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4501 }
4502 $MangledNS .= length($Name).$Name;
4503 add_substitution($MangledNS, $Repl, 0);
4504 return $MangledNS;
4505 }
4506}
4507
4508sub mangle_param($$$)
4509{
4510 my ($PTid, $LibVersion, $Repl) = @_;
4511 my ($MPrefix, $Mangled) = ("", "");
4512 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004513 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004514 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004515 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004516 if(not $BaseType_Name) {
4517 return "";
4518 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004519 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004520 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004521 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4522 while($Suffix=~/(&|\*|const)\Z/)
4523 {
4524 if($Suffix=~s/[ ]*&\Z//) {
4525 $MPrefix .= "R";
4526 }
4527 if($Suffix=~s/[ ]*\*\Z//) {
4528 $MPrefix .= "P";
4529 }
4530 if($Suffix=~s/[ ]*const\Z//)
4531 {
4532 if($MPrefix=~/R|P/
4533 or $Suffix=~/&|\*/) {
4534 $MPrefix .= "K";
4535 }
4536 }
4537 if($Suffix=~s/[ ]*volatile\Z//) {
4538 $MPrefix .= "V";
4539 }
4540 #if($Suffix=~s/[ ]*restrict\Z//) {
4541 #$MPrefix .= "r";
4542 #}
4543 }
4544 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4545 $Mangled .= $Token;
4546 }
4547 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4548 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004549 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004550 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004551 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004552 foreach (@TPos) {
4553 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4554 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004555 }
4556 elsif($TmplParams)
4557 { # remangling mode
4558 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004559 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004560 }
4561 my $MangledNS = "";
4562 my ($SubNS, $SName) = get_sub_ns($ShortName);
4563 if($SubNS) {
4564 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4565 }
4566 $MangledNS .= length($SName).$SName;
4567 if(@TParams) {
4568 add_substitution($MangledNS, $Repl, 0);
4569 }
4570 $Mangled .= "N".$MangledNS;
4571 if(@TParams)
4572 { # templates
4573 $Mangled .= "I";
4574 foreach my $TParam (@TParams) {
4575 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4576 }
4577 $Mangled .= "E";
4578 }
4579 $Mangled .= "E";
4580 }
4581 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4582 {
4583 if($BaseType{"Type"} eq "MethodPtr") {
4584 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4585 }
4586 else {
4587 $Mangled .= "PF";
4588 }
4589 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4590 my @Params = keys(%{$BaseType{"Param"}});
4591 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4592 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4593 }
4594 if(not @Params) {
4595 $Mangled .= "v";
4596 }
4597 $Mangled .= "E";
4598 }
4599 elsif($BaseType{"Type"} eq "FieldPtr")
4600 {
4601 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4602 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4603 }
4604 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4605 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4606 {
4607 if($Mangled eq $Optimized)
4608 {
4609 if($ShortName!~/::/)
4610 { # remove "N ... E"
4611 if($MPrefix) {
4612 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4613 }
4614 else {
4615 $Mangled=~s/\AN(.+)E\Z/$1/g;
4616 }
4617 }
4618 }
4619 else {
4620 $Mangled = $Optimized;
4621 }
4622 }
4623 add_substitution($Mangled, $Repl, 1);
4624 return $Mangled;
4625}
4626
4627sub mangle_template_param($$$)
4628{ # types + literals
4629 my ($TParam, $LibVersion, $Repl) = @_;
4630 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4631 return mangle_param($TPTid, $LibVersion, $Repl);
4632 }
4633 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4634 { # class_name<1u>::method(...)
4635 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4636 }
4637 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4638 { # class_name<(signed char)1>::method(...)
4639 return "L".$IntrinsicMangling{$1}.$2."E";
4640 }
4641 elsif($TParam eq "true")
4642 { # class_name<true>::method(...)
4643 return "Lb1E";
4644 }
4645 elsif($TParam eq "false")
4646 { # class_name<true>::method(...)
4647 return "Lb0E";
4648 }
4649 else { # internal error
4650 return length($TParam).$TParam;
4651 }
4652}
4653
4654sub add_substitution($$$)
4655{
4656 my ($Value, $Repl, $Rec) = @_;
4657 if($Rec)
4658 { # subtypes
4659 my @Subs = ($Value);
4660 while($Value=~s/\A(R|P|K)//) {
4661 push(@Subs, $Value);
4662 }
4663 foreach (reverse(@Subs)) {
4664 add_substitution($_, $Repl, 0);
4665 }
4666 return;
4667 }
4668 return if($Value=~/\AS(\d*)_\Z/);
4669 $Value=~s/\AN(.+)E\Z/$1/g;
4670 return if(defined $Repl->{$Value});
4671 return if(length($Value)<=1);
4672 return if($StdcxxMangling{$Value});
4673 # check for duplicates
4674 my $Base = $Value;
4675 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4676 {
4677 my $Num = $Repl->{$Type};
4678 my $Replace = macro_mangle($Num);
4679 $Base=~s/\Q$Replace\E/$Type/;
4680 }
4681 if(my $OldNum = $Repl->{$Base})
4682 {
4683 $Repl->{$Value} = $OldNum;
4684 return;
4685 }
4686 my @Repls = sort {$b<=>$a} values(%{$Repl});
4687 if(@Repls) {
4688 $Repl->{$Value} = $Repls[0]+1;
4689 }
4690 else {
4691 $Repl->{$Value} = -1;
4692 }
4693 # register duplicates
4694 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004695 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004696 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4697 {
4698 next if($Base eq $Type);
4699 my $Num = $Repl->{$Type};
4700 my $Replace = macro_mangle($Num);
4701 $Base=~s/\Q$Type\E/$Replace/;
4702 $Repl->{$Base} = $Repl->{$Value};
4703 }
4704}
4705
4706sub macro_mangle($)
4707{
4708 my $Num = $_[0];
4709 if($Num==-1) {
4710 return "S_";
4711 }
4712 else
4713 {
4714 my $Code = "";
4715 if($Num<10)
4716 { # S0_, S1_, S2_, ...
4717 $Code = $Num;
4718 }
4719 elsif($Num>=10 and $Num<=35)
4720 { # SA_, SB_, SC_, ...
4721 $Code = chr(55+$Num);
4722 }
4723 else
4724 { # S10_, S11_, S12_
4725 $Code = $Num-26; # 26 is length of english alphabet
4726 }
4727 return "S".$Code."_";
4728 }
4729}
4730
4731sub write_stdcxx_substitution($)
4732{
4733 my $Mangled = $_[0];
4734 if($StdcxxMangling{$Mangled}) {
4735 return $StdcxxMangling{$Mangled};
4736 }
4737 else
4738 {
4739 my @Repls = keys(%StdcxxMangling);
4740 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4741 foreach my $MangledType (@Repls)
4742 {
4743 my $Replace = $StdcxxMangling{$MangledType};
4744 #if($Mangled!~/$Replace/) {
4745 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4746 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4747 #}
4748 }
4749 }
4750 return $Mangled;
4751}
4752
4753sub write_substitution($$)
4754{
4755 my ($Mangled, $Repl) = @_;
4756 if(defined $Repl->{$Mangled}
4757 and my $MnglNum = $Repl->{$Mangled}) {
4758 $Mangled = macro_mangle($MnglNum);
4759 }
4760 else
4761 {
4762 my @Repls = keys(%{$Repl});
4763 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4764 # FIXME: how to apply replacements? by num or by pos
4765 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4766 foreach my $MangledType (@Repls)
4767 {
4768 my $Replace = macro_mangle($Repl->{$MangledType});
4769 if($Mangled!~/$Replace/) {
4770 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4771 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4772 }
4773 }
4774 }
4775 return $Mangled;
4776}
4777
4778sub delete_keywords($)
4779{
4780 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004781 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004782 return $TypeName;
4783}
4784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004785sub uncover_typedefs($$)
4786{
4787 my ($TypeName, $LibVersion) = @_;
4788 return "" if(not $TypeName);
4789 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4790 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4791 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004792 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004793 while($TypeName_New ne $TypeName_Pre)
4794 {
4795 $TypeName_Pre = $TypeName_New;
4796 my $TypeName_Copy = $TypeName_New;
4797 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004798 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004800 if(not $Intrinsic_Keywords{$1}) {
4801 $Words{$1} = 1;
4802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004803 }
4804 foreach my $Word (keys(%Words))
4805 {
4806 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4807 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004808 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004809 if($BaseType_Name=~/\([\*]+\)/)
4810 { # FuncPtr
4811 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4812 {
4813 my $Type_Suffix = $1;
4814 $TypeName_New = $BaseType_Name;
4815 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004816 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004817 }
4818 }
4819 }
4820 else
4821 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004822 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004823 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004824 }
4825 }
4826 }
4827 }
4828 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4829}
4830
4831sub isInternal($)
4832{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004833 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4834 {
4835 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4836 {
4837 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4838 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4839 return 1;
4840 }
4841 }
4842 }
4843 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004844}
4845
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004846sub getDataVal($$)
4847{
4848 my ($InfoId, $TypeId) = @_;
4849 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4850 {
4851 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4852 {
4853 if(defined $LibInfo{$Version}{"info_type"}{$1}
4854 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004855 {
4856 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004857 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004858 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4859 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004860 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004861 if(my $Addr = getTreeAttr_Op($1)) {
4862 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004863 }
4864 }
4865 }
4866 }
4867 else {
4868 return getInitVal($1, $TypeId);
4869 }
4870 }
4871 }
4872 return undef;
4873}
4874
4875sub getInitVal($$)
4876{
4877 my ($InfoId, $TypeId) = @_;
4878 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4879 {
4880 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4881 {
4882 if($InfoType eq "integer_cst")
4883 {
4884 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004885 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004886 { # characters
4887 $Val = chr($Val);
4888 }
4889 return $Val;
4890 }
4891 elsif($InfoType eq "string_cst") {
4892 return getNodeStrCst($InfoId);
4893 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004894 elsif($InfoType eq "var_decl")
4895 {
4896 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4897 return $Name;
4898 }
4899 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004900 }
4901 }
4902 return undef;
4903}
4904
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004905sub set_Class_And_Namespace($)
4906{
4907 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004908 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004909 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004910 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004911 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004912 my $NSInfoId = $1;
4913 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4914 {
4915 if($InfoType eq "namespace_decl") {
4916 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4917 }
4918 elsif($InfoType eq "record_type") {
4919 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4920 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004922 }
4923 }
4924 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4925 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004926 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004927 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004928 { # skip
4929 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004931 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004932
4933 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004934}
4935
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004936sub debugMangling($)
4937{
4938 my $LibVersion = $_[0];
4939 my %Mangled = ();
4940 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4941 {
4942 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4943 {
4944 if($Mngl=~/\A(_Z|\?)/) {
4945 $Mangled{$Mngl}=$InfoId;
4946 }
4947 }
4948 }
4949 translateSymbols(keys(%Mangled), $LibVersion);
4950 foreach my $Mngl (keys(%Mangled))
4951 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004952 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4953 my $U2 = $tr_name{$Mngl};
4954 if($U1 ne $U2) {
4955 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004956 }
4957 }
4958}
4959
4960sub linkSymbol($)
4961{ # link symbols from shared libraries
4962 # with the symbols from header files
4963 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004964 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004965 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004966 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4967 or $EMERGENCY_MODE_48)
4968 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4969 # 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 +03004970 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004971 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004972 {
4973 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4974 return correct_incharge($InfoId, $Version, $Mangled);
4975 }
4976 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004977 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004978 or not $BinaryOnly
4979 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004980 { # 1. --headers-only mode
4981 # 2. not mangled src-only symbols
4982 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4983 return $Mangled;
4984 }
4985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004986 }
4987 return "";
4988}
4989
4990sub setLanguage($$)
4991{
4992 my ($LibVersion, $Lang) = @_;
4993 if(not $UserLang) {
4994 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4995 }
4996}
4997
4998sub getSymbolInfo($)
4999{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005000 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005001 if(isInternal($InfoId)) {
5002 return;
5003 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005004 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5005 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005006 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5007 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005008 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005009 return;
5010 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005011 setFuncAccess($InfoId);
5012 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005013 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5014 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005015 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005016 return;
5017 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005018
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005019 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005020 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005021 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005022 if(not defined $TypeInfo{$Version}{$Return}
5023 or not $TypeInfo{$Version}{$Return}{"Name"})
5024 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005025 delete($SymbolInfo{$Version}{$InfoId});
5026 return;
5027 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005028 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005029 }
5030 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5031 {
5032 if(defined $MissedTypedef{$Version}{$Rid})
5033 {
5034 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5035 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5036 }
5037 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005038 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005039 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5040 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005041 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005042 my $Orig = getFuncOrig($InfoId);
5043 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005044 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5045 {
5046 delete($SymbolInfo{$Version}{$InfoId});
5047 return;
5048 }
5049
5050 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005051 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005052 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005053 return;
5054 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005055
5056 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005057 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005058 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5059
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005060 my @TParams = getTParams($Orig, "Func");
5061 if(not @TParams)
5062 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005063 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005064 return;
5065 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005066 foreach my $Pos (0 .. $#TParams)
5067 {
5068 my $Val = $TParams[$Pos];
5069 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5070
5071 if($Tmpl)
5072 {
5073 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5074 {
5075 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5076 }
5077 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005078 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005079
5080 if($Tmpl)
5081 {
5082 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5083 {
5084 if($Pos>$#TParams)
5085 {
5086 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5087 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5088 }
5089 }
5090 }
5091
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005092 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5093 { # operator<< <T>, operator>> <T>
5094 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5095 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005096 if(@TParams) {
5097 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5098 }
5099 else {
5100 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5101 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005102 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005103 }
5104 else
5105 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005106 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005107 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005108 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5109 {
5110 if($OSgroup eq "windows")
5111 { # cut the offset
5112 $MnglName=~s/\@\d+\Z//g;
5113 }
5114 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5115
5116 # NOTE: mangling of some symbols may change depending on GCC version
5117 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5118 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5119 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005120
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005122 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005123 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005124 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 return;
5126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005129 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005130 if($Skip)
5131 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 return;
5134 }
5135 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005136 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5137 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5138 }
5139
5140 if(set_Class_And_Namespace($InfoId))
5141 {
5142 delete($SymbolInfo{$Version}{$InfoId});
5143 return;
5144 }
5145
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005146 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5147 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005148 if(not defined $TypeInfo{$Version}{$ClassId}
5149 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5150 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005151 delete($SymbolInfo{$Version}{$InfoId});
5152 return;
5153 }
5154 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005155 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5156 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005157 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005158 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005159 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005160 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005161 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005162 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005163 }
5164 if($COMMON_LANGUAGE{$Version} eq "C++")
5165 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005166 # C++ or --headers-only mode
5167 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005168 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005169 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5170 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005171 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005172 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005173 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005174 if(my $Mangled = linkSymbol($InfoId)) {
5175 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005176 }
5177 }
5178 if($OStarget eq "windows")
5179 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005180 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005181 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005182 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005183 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005184 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005186 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 }
5188 }
5189 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005190 else
5191 { # not mangled in C
5192 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5193 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005194 if(not $CheckHeadersOnly
5195 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5196 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5197 {
5198 my $Incorrect = 0;
5199
5200 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5201 {
5202 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5203 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5204 { # mangled in the TU dump, but not mangled in the library
5205 $Incorrect = 1;
5206 }
5207 }
5208 else
5209 {
5210 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5211 { # all C++ functions are not mangled in the TU dump
5212 $Incorrect = 1;
5213 }
5214 }
5215 if($Incorrect)
5216 {
5217 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5218 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5219 }
5220 }
5221 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005222 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005223 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005224 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005225 return;
5226 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005227 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005228 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005229 { # identify virtual and pure virtual functions
5230 # NOTE: constructors cannot be virtual
5231 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5232 # in the TU dump, so taking it from the original symbol
5233 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5234 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5235 { # NOTE: D2 destructors are not present in a v-table
5236 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005239 if(isInline($InfoId)) {
5240 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005242 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005243 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5246 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005247 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005249 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005251 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 }
5253 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005254 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5255 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005256 if(not $ExtraDump)
5257 {
5258 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5259 { # non-target symbols
5260 delete($SymbolInfo{$Version}{$InfoId});
5261 return;
5262 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005265 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5266 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5267 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5268 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005269 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005270 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5271 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005272 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 return;
5274 }
5275 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005276 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005277 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005279 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005280 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 return;
5282 }
5283 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005284 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 }
5286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005287 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5288 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5289 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005291 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5292 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005294 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005295 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005296 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005297 }
5298 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 if(getFuncLink($InfoId) eq "Static") {
5300 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005301 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005302 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5303 {
5304 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5305 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005306 if($Unmangled=~/\.\_\d/)
5307 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005308 delete($SymbolInfo{$Version}{$InfoId});
5309 return;
5310 }
5311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005312 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005313
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005314 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5315 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005317 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5318 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005319 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005320
5321 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5322 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5323 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005324
5325 if($ExtraDump) {
5326 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5327 }
5328}
5329
5330sub guessHeader($)
5331{
5332 my $InfoId = $_[0];
5333 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5334 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5335 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5336 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5337 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5338 {
5339 if(get_filename($HPath) eq $Header)
5340 {
5341 my $HDir = get_filename(get_dirname($HPath));
5342 if($HDir ne "include"
5343 and $HDir=~/\A[a-z]+\Z/i) {
5344 return join_P($HDir, $Header);
5345 }
5346 }
5347 }
5348 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005349}
5350
5351sub isInline($)
5352{ # "body: undefined" in the tree
5353 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005354 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5355 {
5356 if($Info=~/ undefined /i) {
5357 return 0;
5358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359 }
5360 return 1;
5361}
5362
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005363sub hasThrow($)
5364{
5365 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5366 {
5367 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5368 return getTreeAttr_Unql($1, "unql");
5369 }
5370 }
5371 return 1;
5372}
5373
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005374sub getTypeId($)
5375{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005376 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5377 {
5378 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5379 return $1;
5380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005381 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005382 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005383}
5384
5385sub setTypeMemb($$)
5386{
5387 my ($TypeId, $TypeAttr) = @_;
5388 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005389 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005390 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391 if($TypeType eq "Enum")
5392 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005393 my $MInfoId = getTreeAttr_Csts($TypeId);
5394 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005396 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5397 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005398 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005399 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5400 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005401 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
5403 }
5404 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5405 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005406 my $MInfoId = getTreeAttr_Flds($TypeId);
5407 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005408 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005409 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5410 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005411 if(not $IType or $IType ne "field_decl")
5412 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005413
5414 if($IType eq "var_decl")
5415 { # static field
5416 $StaticFields = 1;
5417 }
5418
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005419 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005420 next;
5421 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005422 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005423 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005424 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005425 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426 }
5427 if(not $StructMembName)
5428 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005429 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005430 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005431 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5433 if(isAnon($UnnamedTName))
5434 { # rename unnamed fields to unnamed0, unnamed1, ...
5435 $StructMembName = "unnamed".($UnnamedPos++);
5436 }
5437 }
5438 }
5439 if(not $StructMembName)
5440 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005441 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005442 next;
5443 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005444 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005445 if(defined $MissedTypedef{$Version}{$MembTypeId})
5446 {
5447 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5448 $MembTypeId = $AddedTid;
5449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005450 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005451
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005452 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5453 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005454 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005455 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005456 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5457 }
5458 if($MInfo=~/spec:\s*mutable /)
5459 { # mutable fields
5460 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005461 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005462 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005463 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5464 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005466 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005467 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005468 }
5469 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005470 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005471 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5472 { # template
5473 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5474 }
5475 else {
5476 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5477 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005478 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005479
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005480 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005481 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 }
5483 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005484
5485 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005486}
5487
5488sub setFuncParams($)
5489{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005490 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005491 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005492
5493 my $FType = getFuncType($InfoId);
5494
5495 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005496 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005497 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5498 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005499 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005500 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005501 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5502 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005503 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005504 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005506 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005507 else
5508 { # skip
5509 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005510 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005511 # skip "this"-parameter
5512 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005514 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005515 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005516 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005517 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5518 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5519 if(not $ParamName)
5520 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005521 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005522 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005523 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5524 {
5525 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5526 $ParamTypeId = $AddedTid;
5527 }
5528 }
5529 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005530 if(not $PType or $PType eq "Unknown") {
5531 return 1;
5532 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005533 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005534 if(not $PTName) {
5535 return 1;
5536 }
5537 if($PTName eq "void") {
5538 last;
5539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005540 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005541 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005542 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005543 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005544 $ParamInfoId = getNextElem($ParamInfoId);
5545 next;
5546 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005547 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005548
5549 if(my %Base = get_BaseType($ParamTypeId, $Version))
5550 {
5551 if(defined $Base{"Template"}) {
5552 return 1;
5553 }
5554 }
5555
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005556 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005557 if(my $Algn = getAlgn($ParamInfoId)) {
5558 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005560 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5561 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005562 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 }
5564 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005565 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005566 if($ParamName ne "this" or $FType ne "Method") {
5567 $PPos += 1;
5568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005569 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005570 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005571 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 }
5573 return 0;
5574}
5575
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005576sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005577{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005578 my ($InfoId, $Vtt_Pos) = @_;
5579 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005580 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005581 my $FType = getFuncType($InfoId);
5582
5583 if($FType eq "Method")
5584 {
5585 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005586 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005587 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005588 if(not $ParamListElemId)
5589 { # foo(...)
5590 return 1;
5591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005592 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005593 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005594 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005595 { # actual params: may differ from formal args
5596 # formal int*const
5597 # actual: int*
5598 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 {
5600 $Vtt_Pos=-1;
5601 $ParamListElemId = getNextElem($ParamListElemId);
5602 next;
5603 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005604 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5605 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005606 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005607 $HaveVoid = 1;
5608 last;
5609 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005610 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005611 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005612 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5613 {
5614 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5615 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5616 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005617 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005618 }
5619 }
5620 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5621 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005622 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005623 { # params
5624 if($OldId ne $ParamTypeId)
5625 {
5626 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5627 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5628
5629 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5630 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5631 }
5632 }
5633 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005634 }
5635 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005636 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005637 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005638 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5639 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005640 if($PurpType eq "nop_expr")
5641 { # func ( const char* arg = (const char*)(void*)0 )
5642 $PurpId = getTreeAttr_Op($PurpId);
5643 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005644 my $Val = getInitVal($PurpId, $ParamTypeId);
5645 if(defined $Val) {
5646 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005648 }
5649 }
5650 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005651 if($Pos!=0 or $FType ne "Method") {
5652 $PPos += 1;
5653 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005654 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005655 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005656 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005657}
5658
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005659sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005660{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005661 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5662 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005663 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5664 return $1;
5665 }
5666 }
5667 return "";
5668}
5669
5670sub getTreeAttr_Chain($)
5671{
5672 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5673 {
5674 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5675 return $1;
5676 }
5677 }
5678 return "";
5679}
5680
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005681sub getTreeAttr_Unql($)
5682{
5683 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5684 {
5685 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5686 return $1;
5687 }
5688 }
5689 return "";
5690}
5691
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005692sub getTreeAttr_Scpe($)
5693{
5694 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5695 {
5696 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5697 return $1;
5698 }
5699 }
5700 return "";
5701}
5702
5703sub getTreeAttr_Type($)
5704{
5705 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5706 {
5707 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5708 return $1;
5709 }
5710 }
5711 return "";
5712}
5713
5714sub getTreeAttr_Name($)
5715{
5716 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5717 {
5718 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5719 return $1;
5720 }
5721 }
5722 return "";
5723}
5724
5725sub getTreeAttr_Mngl($)
5726{
5727 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5728 {
5729 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5730 return $1;
5731 }
5732 }
5733 return "";
5734}
5735
5736sub getTreeAttr_Prms($)
5737{
5738 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5739 {
5740 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5741 return $1;
5742 }
5743 }
5744 return "";
5745}
5746
5747sub getTreeAttr_Fncs($)
5748{
5749 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5750 {
5751 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5752 return $1;
5753 }
5754 }
5755 return "";
5756}
5757
5758sub getTreeAttr_Csts($)
5759{
5760 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5761 {
5762 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5763 return $1;
5764 }
5765 }
5766 return "";
5767}
5768
5769sub getTreeAttr_Purp($)
5770{
5771 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5772 {
5773 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5774 return $1;
5775 }
5776 }
5777 return "";
5778}
5779
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005780sub getTreeAttr_Op($)
5781{
5782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5783 {
5784 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5785 return $1;
5786 }
5787 }
5788 return "";
5789}
5790
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005791sub getTreeAttr_Valu($)
5792{
5793 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5794 {
5795 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5796 return $1;
5797 }
5798 }
5799 return "";
5800}
5801
5802sub getTreeAttr_Flds($)
5803{
5804 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5805 {
5806 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5807 return $1;
5808 }
5809 }
5810 return "";
5811}
5812
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005813sub getTreeAttr_Binf($)
5814{
5815 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5816 {
5817 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5818 return $1;
5819 }
5820 }
5821 return "";
5822}
5823
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005824sub getTreeAttr_Args($)
5825{
5826 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5827 {
5828 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005829 return $1;
5830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005831 }
5832 return "";
5833}
5834
5835sub getTreeValue($)
5836{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005837 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5838 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005839 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5840 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005842 }
5843 return "";
5844}
5845
5846sub getTreeAccess($)
5847{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005848 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005849 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005850 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5851 {
5852 my $Access = $1;
5853 if($Access eq "prot") {
5854 return "protected";
5855 }
5856 elsif($Access eq "priv") {
5857 return "private";
5858 }
5859 }
5860 elsif($Info=~/ protected /)
5861 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005862 return "protected";
5863 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005864 elsif($Info=~/ private /)
5865 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005866 return "private";
5867 }
5868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005869 return "public";
5870}
5871
5872sub setFuncAccess($)
5873{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005874 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005875 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005876 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005877 }
5878 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005879 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005880 }
5881}
5882
5883sub setTypeAccess($$)
5884{
5885 my ($TypeId, $TypeAttr) = @_;
5886 my $Access = getTreeAccess($TypeId);
5887 if($Access eq "protected") {
5888 $TypeAttr->{"Protected"} = 1;
5889 }
5890 elsif($Access eq "private") {
5891 $TypeAttr->{"Private"} = 1;
5892 }
5893}
5894
5895sub setFuncKind($)
5896{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005897 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5898 {
5899 if($Info=~/pseudo tmpl/) {
5900 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5901 }
5902 elsif($Info=~/ constructor /) {
5903 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5904 }
5905 elsif($Info=~/ destructor /) {
5906 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005908 }
5909}
5910
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005911sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005912{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005913 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5914 {
5915 if($Info=~/spec[ ]*:[ ]*pure /) {
5916 return "PureVirt";
5917 }
5918 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5919 return "Virt";
5920 }
5921 elsif($Info=~/ pure\s+virtual /)
5922 { # support for old GCC versions
5923 return "PureVirt";
5924 }
5925 elsif($Info=~/ virtual /)
5926 { # support for old GCC versions
5927 return "Virt";
5928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 }
5930 return "";
5931}
5932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933sub getFuncLink($)
5934{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005935 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5936 {
5937 if($Info=~/link[ ]*:[ ]*static /) {
5938 return "Static";
5939 }
5940 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005941 return $1;
5942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005943 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005944 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005945}
5946
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005947sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005948{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005949 my ($Symbol, $LibVersion) = @_;
5950 return "" if(not $Symbol or not $LibVersion);
5951 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5952 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005953 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005954 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5955 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5956 }
5957 }
5958 if($NS)
5959 {
5960 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5961 return $NS;
5962 }
5963 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005964 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005965 while($NS=~s/::[^:]+\Z//)
5966 {
5967 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5968 return $NS;
5969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005970 }
5971 }
5972 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005973
5974 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005975}
5976
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005977sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978{
5979 my ($TypeName, $LibVersion) = @_;
5980 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005981 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005982 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005983 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5984 return $NS;
5985 }
5986 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005988 while($NS=~s/::[^:]+\Z//)
5989 {
5990 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5991 return $NS;
5992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005993 }
5994 }
5995 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005996 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997}
5998
5999sub getNameSpace($)
6000{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006001 my $InfoId = $_[0];
6002 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006004 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006005 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006006 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006007 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006008 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6009 {
6010 my $NameSpace = getTreeStr($1);
6011 if($NameSpace eq "::")
6012 { # global namespace
6013 return "";
6014 }
6015 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6016 $NameSpace = $BaseNameSpace."::".$NameSpace;
6017 }
6018 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6019 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006020 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006021 else {
6022 return "";
6023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006025 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006026 { # inside data type
6027 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6028 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006031 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006032 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006033}
6034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035sub getEnumMembVal($)
6036{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006037 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006039 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6040 {
6041 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6042 {
6043 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6044 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6045 return getTreeValue($1);
6046 }
6047 else
6048 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6049 return getTreeValue($1);
6050 }
6051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052 }
6053 }
6054 return "";
6055}
6056
6057sub getSize($)
6058{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006059 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6060 {
6061 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6062 return getTreeValue($1);
6063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006065 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066}
6067
6068sub getAlgn($)
6069{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006070 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6071 {
6072 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6073 return $1;
6074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006076 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077}
6078
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006079sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006080{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006081 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6082 {
6083 if($Info=~/ bitfield /) {
6084 return getSize($_[0]);
6085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006086 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006087 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006088}
6089
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006090sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006091{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006092 if(my $Chan = getTreeAttr_Chan($_[0])) {
6093 return $Chan;
6094 }
6095 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6096 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006097 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006098 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099}
6100
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006101sub registerHeader($$)
6102{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006103 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006104 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006105 return "";
6106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006107 if(is_abs($Header) and not -f $Header)
6108 { # incorrect absolute path
6109 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006110 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006111 if(skipHeader($Header, $LibVersion))
6112 { # skip
6113 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006115 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6116 {
6117 detect_header_includes($Header_Path, $LibVersion);
6118
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006119 if(defined $Tolerance and $Tolerance=~/3/)
6120 { # 3 - skip headers that include non-Linux headers
6121 if($OSgroup ne "windows")
6122 {
6123 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6124 {
6125 if(specificHeader($Inc, "windows")) {
6126 return "";
6127 }
6128 }
6129 }
6130 }
6131
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6133 { # redirect
6134 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6135 or skipHeader($RHeader_Path, $LibVersion))
6136 { # skip
6137 return "";
6138 }
6139 $Header_Path = $RHeader_Path;
6140 }
6141 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6142 { # skip
6143 return "";
6144 }
6145
6146 if(my $HName = get_filename($Header_Path))
6147 { # register
6148 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6149 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6150 }
6151
6152 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6153 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006154 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006155 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006156 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006157 }
6158
6159 if($CheckHeadersOnly
6160 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6161 { # /usr/include/c++/4.6.1/...
6162 $STDCXX_TESTING = 1;
6163 }
6164
6165 return $Header_Path;
6166 }
6167 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006168}
6169
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006170sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006171{
6172 my ($Dir, $WithDeps, $LibVersion) = @_;
6173 $Dir=~s/[\/\\]+\Z//g;
6174 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006175 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006176
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006177 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006178 if($WithDeps)
6179 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006180 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6181 return;
6182 }
6183 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6184 $Mode = "DepsOnly";
6185 }
6186 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006187 else
6188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6190 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6191 return;
6192 }
6193 }
6194 $Header_Dependency{$LibVersion}{$Dir} = 1;
6195 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6196 if($Mode eq "DepsOnly")
6197 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006198 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006199 $Header_Dependency{$LibVersion}{$Path} = 1;
6200 }
6201 return;
6202 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006203 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006204 {
6205 if($WithDeps)
6206 {
6207 my $SubDir = $Path;
6208 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6209 { # register all sub directories
6210 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6211 }
6212 }
6213 next if(is_not_header($Path));
6214 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006215 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006216 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006217 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6218 }
6219 }
6220 if(get_filename($Dir) eq "include")
6221 { # search for "lib/include/" directory
6222 my $LibDir = $Dir;
6223 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006224 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 }
6226 }
6227}
6228
6229sub parse_redirect($$$)
6230{
6231 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006232 my @Errors = ();
6233 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6234 push(@Errors, $1);
6235 }
6236 my $Redirect = "";
6237 foreach (@Errors)
6238 {
6239 s/\s{2,}/ /g;
6240 if(/(only|must\ include
6241 |update\ to\ include
6242 |replaced\ with
6243 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006244 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006245 {
6246 $Redirect = $2;
6247 last;
6248 }
6249 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6250 {
6251 $Redirect = $2;
6252 last;
6253 }
6254 elsif(/this\ header\ should\ not\ be\ used
6255 |programs\ should\ not\ directly\ include
6256 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6257 |is\ not\ supported\ API\ for\ general\ use
6258 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006259 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006260 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6261 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6262 }
6263 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006264 if($Redirect)
6265 {
6266 $Redirect=~s/\A<//g;
6267 $Redirect=~s/>\Z//g;
6268 }
6269 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006270}
6271
6272sub parse_includes($$)
6273{
6274 my ($Content, $Path) = @_;
6275 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006276 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006277 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006278 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006279 my $Method = substr($Header, 0, 1, "");
6280 substr($Header, length($Header)-1, 1, "");
6281 $Header = path_format($Header, $OSgroup);
6282 if($Method eq "\"" or is_abs($Header))
6283 {
6284 if(-e join_P(get_dirname($Path), $Header))
6285 { # relative path exists
6286 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006287 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006288 else
6289 { # include "..." that doesn't exist is equal to include <...>
6290 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006293 else {
6294 $Includes{$Header} = 1;
6295 }
6296 }
6297 if($ExtraInfo)
6298 {
6299 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6300 { # FT_FREETYPE_H
6301 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006302 }
6303 }
6304 return \%Includes;
6305}
6306
6307sub ignore_path($)
6308{
6309 my $Path = $_[0];
6310 if($Path=~/\~\Z/)
6311 {# skipping system backup files
6312 return 1;
6313 }
6314 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6315 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6316 return 1;
6317 }
6318 return 0;
6319}
6320
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006321sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322{
6323 my ($ArrRef, $W) = @_;
6324 return if(length($W)<2);
6325 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6326}
6327
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006328sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006329{
6330 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 $H1=~s/\.[a-z]+\Z//ig;
6333 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006334
6335 my $Hname1 = get_filename($H1);
6336 my $Hname2 = get_filename($H2);
6337 my $HDir1 = get_dirname($H1);
6338 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006339 my $Dirname1 = get_filename($HDir1);
6340 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006341
6342 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6343 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6344
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006345 if($_[0] eq $_[1]
6346 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006347 return 0;
6348 }
6349 elsif($H1=~/\A\Q$H2\E/) {
6350 return 1;
6351 }
6352 elsif($H2=~/\A\Q$H1\E/) {
6353 return -1;
6354 }
6355 elsif($HDir1=~/\Q$Hname1\E/i
6356 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006357 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006358 return -1;
6359 }
6360 elsif($HDir2=~/\Q$Hname2\E/i
6361 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006362 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006363 return 1;
6364 }
6365 elsif($Hname1=~/\Q$Dirname1\E/i
6366 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006367 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 return -1;
6369 }
6370 elsif($Hname2=~/\Q$Dirname2\E/i
6371 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006372 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006373 return 1;
6374 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006375 elsif($Hname1=~/(config|lib|util)/i
6376 and $Hname2!~/(config|lib|util)/i)
6377 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006378 return -1;
6379 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006380 elsif($Hname2=~/(config|lib|util)/i
6381 and $Hname1!~/(config|lib|util)/i)
6382 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006383 return 1;
6384 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006385 else
6386 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006387 my $R1 = checkRelevance($H1);
6388 my $R2 = checkRelevance($H2);
6389 if($R1 and not $R2)
6390 { # libebook/e-book.h
6391 return -1;
6392 }
6393 elsif($R2 and not $R1)
6394 { # libebook/e-book.h
6395 return 1;
6396 }
6397 else
6398 {
6399 return (lc($H1) cmp lc($H2));
6400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006401 }
6402}
6403
6404sub searchForHeaders($)
6405{
6406 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006408 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006409 registerGccHeaders();
6410
6411 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6412 { # c++ standard include paths
6413 registerCppHeaders();
6414 }
6415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006416 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006417 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6418 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006419 {
6420 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006421 if($SystemRoot)
6422 {
6423 if(is_abs($Path)) {
6424 $Path = $SystemRoot.$Path;
6425 }
6426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006427 if(not -e $Path) {
6428 exitStatus("Access_Error", "can't access \'$Path\'");
6429 }
6430 elsif(-f $Path) {
6431 exitStatus("Access_Error", "\'$Path\' - not a directory");
6432 }
6433 elsif(-d $Path)
6434 {
6435 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006436 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006437 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6438 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006439 }
6440 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006441 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006442 }
6443 }
6444 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006445 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006446 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6447 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006449 # registering directories
6450 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6451 {
6452 next if(not -e $Path);
6453 $Path = get_abs_path($Path);
6454 $Path = path_format($Path, $OSgroup);
6455 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006456 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 }
6458 elsif(-f $Path)
6459 {
6460 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006461 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006462 and not $LocalIncludes{$Dir})
6463 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006464 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006465 # if(my $OutDir = get_dirname($Dir))
6466 # { # registering the outer directory
6467 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6468 # and not $LocalIncludes{$OutDir}) {
6469 # registerDir($OutDir, 0, $LibVersion);
6470 # }
6471 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006472 }
6473 }
6474 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006475
6476 # clean memory
6477 %RegisteredDirs = ();
6478
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006479 # registering headers
6480 my $Position = 0;
6481 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6482 {
6483 if(is_abs($Dest) and not -e $Dest) {
6484 exitStatus("Access_Error", "can't access \'$Dest\'");
6485 }
6486 $Dest = path_format($Dest, $OSgroup);
6487 if(is_header($Dest, 1, $LibVersion))
6488 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006489 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6491 }
6492 }
6493 elsif(-d $Dest)
6494 {
6495 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006496 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006497 {
6498 next if(ignore_path($Path));
6499 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006500 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006501 push(@Registered, $HPath);
6502 }
6503 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006504 @Registered = sort {sortHeaders($a, $b)} @Registered;
6505 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006506 foreach my $Path (@Registered) {
6507 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6508 }
6509 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006510 elsif(not defined $SkipUnidentified) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6512 }
6513 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006514
6515 if(defined $Tolerance and $Tolerance=~/4/)
6516 { # 4 - skip headers included by others
6517 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6518 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006519 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006520 delete($Registered_Headers{$LibVersion}{$Path});
6521 }
6522 }
6523 }
6524
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006525 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6526 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006527 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006528 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006529 if(is_abs($Header) and not -f $Header) {
6530 exitStatus("Access_Error", "can't access file \'$Header\'");
6531 }
6532 $Header = path_format($Header, $OSgroup);
6533 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006535 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006536 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006537 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03006538 elsif($SkipUnidentified) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006539 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006541 }
6542 }
6543 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6544 { # set relative paths (for duplicates)
6545 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6546 { # search for duplicates
6547 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6548 my $Prefix = get_dirname($FirstPath);
6549 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6550 { # detect a shortest distinguishing prefix
6551 my $NewPrefix = $1;
6552 my %Identity = ();
6553 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6554 {
6555 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6556 $Identity{$Path} = $1;
6557 }
6558 }
6559 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006560 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006561 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6562 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6563 }
6564 last;
6565 }
6566 $Prefix = $NewPrefix; # increase prefix
6567 }
6568 }
6569 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006570
6571 # clean memory
6572 %HeaderName_Paths = ();
6573
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006574 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6575 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006576 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006577 my ($Pos, $PairPos) = (-1, -1);
6578 my ($Path, $PairPath) = ();
6579 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6580 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6581 foreach my $Header_Path (@Paths)
6582 {
6583 if(get_filename($Header_Path) eq $PairName)
6584 {
6585 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6586 $PairPath = $Header_Path;
6587 }
6588 if(get_filename($Header_Path) eq $HeaderName)
6589 {
6590 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6591 $Path = $Header_Path;
6592 }
6593 }
6594 if($PairPos!=-1 and $Pos!=-1
6595 and int($PairPos)<int($Pos))
6596 {
6597 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6598 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6599 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6600 }
6601 }
6602 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6603 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6604 }
6605}
6606
6607sub detect_real_includes($$)
6608{
6609 my ($AbsPath, $LibVersion) = @_;
6610 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6611 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6612 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6613 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6614 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006615 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006617 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6618 return () if(not $Path);
6619 open(PREPROC, $Path);
6620 while(<PREPROC>)
6621 {
6622 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6623 {
6624 my $Include = path_format($1, $OSgroup);
6625 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6626 next;
6627 }
6628 if($Include eq $AbsPath) {
6629 next;
6630 }
6631 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6632 }
6633 }
6634 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006635 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6636}
6637
6638sub detect_header_includes($$)
6639{
6640 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006641 return if(not $LibVersion or not $Path);
6642 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6643 return;
6644 }
6645 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6646
6647 if(not -e $Path) {
6648 return;
6649 }
6650
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006652 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6653 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006654 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006655 {
6656 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006657 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658 }
6659 if($RedirectPath ne $Path) {
6660 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6661 }
6662 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006663 else
6664 { # can't find
6665 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006668 if(my $Inc = parse_includes($Content, $Path))
6669 {
6670 foreach my $Include (keys(%{$Inc}))
6671 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006672 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006673
6674 if(defined $Tolerance and $Tolerance=~/4/)
6675 {
6676 if(my $HPath = identifyHeader($Include, $LibVersion))
6677 {
6678 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6679 }
6680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006681 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006683}
6684
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006685sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006686{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006687 my $Path = $_[0];
6688 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006689 if($OStarget eq "symbian")
6690 {
6691 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6692 { # epoc32/include/libc/{stdio, ...}.h
6693 return 1;
6694 }
6695 }
6696 else
6697 {
6698 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6699 { # /usr/include/{stdio, ...}.h
6700 return 1;
6701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 return 0;
6704}
6705
6706sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006707{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 my $Dir = $_[0];
6709 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006710 if($OStarget eq "symbian")
6711 {
6712 if(get_filename($OutDir) eq "libc"
6713 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6714 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6715 return 1;
6716 }
6717 }
6718 else
6719 { # linux
6720 if($OutDir eq "/usr/include"
6721 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6722 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6723 return 1;
6724 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 }
6726 return 0;
6727}
6728
6729sub detect_recursive_includes($$)
6730{
6731 my ($AbsPath, $LibVersion) = @_;
6732 return () if(not $AbsPath);
6733 if(isCyclical(\@RecurInclude, $AbsPath)) {
6734 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6735 }
6736 my ($AbsDir, $Name) = separate_path($AbsPath);
6737 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006738 { # system GLIBC internals
6739 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006740 }
6741 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6742 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6743 }
6744 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006745
6746 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6747 { # skip /usr/include/c++/*/ headers
6748 return () if(not $ExtraInfo);
6749 }
6750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006752 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006753 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006754 { # check "real" (non-"model") include paths
6755 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6756 pop(@RecurInclude);
6757 return @Paths;
6758 }
6759 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6760 detect_header_includes($AbsPath, $LibVersion);
6761 }
6762 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6763 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006764 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006765 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006766 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006767 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006768 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006769 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006770 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006771 }
6772 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006773 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006774 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 { # search for the nearest header
6776 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006777 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006778 if(-f $Candidate) {
6779 $HPath = $Candidate;
6780 }
6781 }
6782 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006783 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006784 }
6785 next if(not $HPath);
6786 if($HPath eq $AbsPath) {
6787 next;
6788 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006789
6790 if($Debug)
6791 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006792# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6793# {
6794# print STDERR "$AbsPath -> $HPath\n";
6795# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006796 }
6797
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006798 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6799 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006800 { # only include <...>, skip include "..." prefixes
6801 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6802 }
6803 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6804 {
6805 if($IncPath eq $AbsPath) {
6806 next;
6807 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006808 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6809 if($RIncType==-1)
6810 { # include "..."
6811 $RIncType = $IncType;
6812 }
6813 elsif($RIncType==2)
6814 {
6815 if($IncType!=-1) {
6816 $RIncType = $IncType;
6817 }
6818 }
6819 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006820 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6821 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6822 }
6823 }
6824 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6825 {
6826 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6827 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6828 { # distinguish math.h from glibc and math.h from the tested library
6829 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6830 last;
6831 }
6832 }
6833 }
6834 pop(@RecurInclude);
6835 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6836}
6837
6838sub find_in_framework($$$)
6839{
6840 my ($Header, $Framework, $LibVersion) = @_;
6841 return "" if(not $Header or not $Framework or not $LibVersion);
6842 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6843 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6844 }
6845 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6846 {
6847 if(get_filename($Dependency) eq $Framework
6848 and -f get_dirname($Dependency)."/".$Header) {
6849 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6850 }
6851 }
6852 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6853}
6854
6855sub find_in_defaults($)
6856{
6857 my $Header = $_[0];
6858 return "" if(not $Header);
6859 if(defined $Cache{"find_in_defaults"}{$Header}) {
6860 return $Cache{"find_in_defaults"}{$Header};
6861 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006862 foreach my $Dir (@DefaultIncPaths,
6863 @DefaultGccPaths,
6864 @DefaultCppPaths,
6865 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006866 {
6867 next if(not $Dir);
6868 if(-f $Dir."/".$Header) {
6869 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6870 }
6871 }
6872 return ($Cache{"find_in_defaults"}{$Header}="");
6873}
6874
6875sub cmp_paths($$)
6876{
6877 my ($Path1, $Path2) = @_;
6878 my @Parts1 = split(/[\/\\]/, $Path1);
6879 my @Parts2 = split(/[\/\\]/, $Path2);
6880 foreach my $Num (0 .. $#Parts1)
6881 {
6882 my $Part1 = $Parts1[$Num];
6883 my $Part2 = $Parts2[$Num];
6884 if($GlibcDir{$Part1}
6885 and not $GlibcDir{$Part2}) {
6886 return 1;
6887 }
6888 elsif($GlibcDir{$Part2}
6889 and not $GlibcDir{$Part1}) {
6890 return -1;
6891 }
6892 elsif($Part1=~/glib/
6893 and $Part2!~/glib/) {
6894 return 1;
6895 }
6896 elsif($Part1!~/glib/
6897 and $Part2=~/glib/) {
6898 return -1;
6899 }
6900 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6901 return $CmpRes;
6902 }
6903 }
6904 return 0;
6905}
6906
6907sub checkRelevance($)
6908{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006909 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006910 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006911
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006912 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006913 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006914 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006915
6916 my $Name = lc(get_filename($Path));
6917 my $Dir = lc(get_dirname($Path));
6918
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006919 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006920
6921 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006922 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006923 my $Len = length($Token);
6924 next if($Len<=1);
6925 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6926 { # include/evolution-data-server-1.4/libebook/e-book.h
6927 return 1;
6928 }
6929 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006930 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 return 1;
6932 }
6933 }
6934 return 0;
6935}
6936
6937sub checkFamily(@)
6938{
6939 my @Paths = @_;
6940 return 1 if($#Paths<=0);
6941 my %Prefix = ();
6942 foreach my $Path (@Paths)
6943 {
6944 if($SystemRoot) {
6945 $Path = cut_path_prefix($Path, $SystemRoot);
6946 }
6947 if(my $Dir = get_dirname($Path))
6948 {
6949 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6950 $Prefix{$Dir} += 1;
6951 $Prefix{get_dirname($Dir)} += 1;
6952 }
6953 }
6954 foreach (sort keys(%Prefix))
6955 {
6956 if(get_depth($_)>=3
6957 and $Prefix{$_}==$#Paths+1) {
6958 return 1;
6959 }
6960 }
6961 return 0;
6962}
6963
6964sub isAcceptable($$$)
6965{
6966 my ($Header, $Candidate, $LibVersion) = @_;
6967 my $HName = get_filename($Header);
6968 if(get_dirname($Header))
6969 { # with prefix
6970 return 1;
6971 }
6972 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6973 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6974 return 1;
6975 }
6976 if(checkRelevance($Candidate))
6977 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6978 return 1;
6979 }
6980 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6981 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6982 # /usr/include/qt4/Qt/qsslconfiguration.h
6983 return 1;
6984 }
6985 if($OStarget eq "symbian")
6986 {
6987 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6988 return 1;
6989 }
6990 }
6991 return 0;
6992}
6993
6994sub isRelevant($$$)
6995{ # disallow to search for "abstract" headers in too deep directories
6996 my ($Header, $Candidate, $LibVersion) = @_;
6997 my $HName = get_filename($Header);
6998 if($OStarget eq "symbian")
6999 {
7000 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7001 return 0;
7002 }
7003 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007004 if($OStarget ne "bsd")
7005 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007006 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7007 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7008 return 0;
7009 }
7010 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007011 if($OStarget ne "windows")
7012 {
7013 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7014 { # skip /usr/include/wine/msvcrt
7015 return 0;
7016 }
7017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007018 if(not get_dirname($Header)
7019 and $Candidate=~/[\/\\]wx[\/\\]/)
7020 { # do NOT search in system /wx/ directory
7021 # for headers without a prefix: sstream.h
7022 return 0;
7023 }
7024 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7025 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7026 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7027 return 0;
7028 }
7029 if($Candidate=~/[\/\\]asm-/
7030 and (my $Arch = getArch($LibVersion)) ne "unknown")
7031 { # arch-specific header files
7032 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7033 {# skip ../asm-arm/ if using x86 architecture
7034 return 0;
7035 }
7036 }
7037 my @Candidates = getSystemHeaders($HName, $LibVersion);
7038 if($#Candidates==1)
7039 { # unique header
7040 return 1;
7041 }
7042 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7043 if($#SCandidates==1)
7044 { # unique name
7045 return 1;
7046 }
7047 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7048 if(get_depth($Candidate)-$SystemDepth>=5)
7049 { # abstract headers in too deep directories
7050 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7051 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7052 return 0;
7053 }
7054 }
7055 if($Header eq "parser.h"
7056 and $Candidate!~/\/libxml2\//)
7057 { # select parser.h from xml2 library
7058 return 0;
7059 }
7060 if(not get_dirname($Header)
7061 and keys(%{$SystemHeaders{$HName}})>=3)
7062 { # many headers with the same name
7063 # like thread.h included without a prefix
7064 if(not checkFamily(@Candidates)) {
7065 return 0;
7066 }
7067 }
7068 return 1;
7069}
7070
7071sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007072{ # cache function
7073 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7074 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7075 }
7076 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7077}
7078
7079sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007080{
7081 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007082 if(-f $Header) {
7083 return $Header;
7084 }
7085 if(is_abs($Header) and not -f $Header)
7086 { # incorrect absolute path
7087 return "";
7088 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007089 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007090 { # too abstract configuration headers
7091 return "";
7092 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007093 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007094 if($OSgroup ne "windows")
7095 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007096 if(defined $WinHeaders{lc($HName)}
7097 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007098 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007099 return "";
7100 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007101 }
7102 if($OSgroup ne "macos")
7103 {
7104 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007105 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007106 return "";
7107 }
7108 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007109
7110 if(defined $ObsoleteHeaders{$HName})
7111 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007112 return "";
7113 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007114 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7115 {
7116 if(defined $AlienHeaders{$HName}
7117 or defined $AlienHeaders{$Header})
7118 { # alien headers from other systems
7119 return "";
7120 }
7121 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007122
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007123 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007124 { # search in default paths
7125 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007126 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 }
7128 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007129 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007130 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007131 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007132 }
7133 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7134 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7135 {
7136 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007137 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007138 }
7139 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007140 # error
7141 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007142}
7143
7144sub getSystemHeaders($$)
7145{
7146 my ($Header, $LibVersion) = @_;
7147 my @Candidates = ();
7148 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7149 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007150 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007151 next;
7152 }
7153 push(@Candidates, $Candidate);
7154 }
7155 return @Candidates;
7156}
7157
7158sub cut_path_prefix($$)
7159{
7160 my ($Path, $Prefix) = @_;
7161 return $Path if(not $Prefix);
7162 $Prefix=~s/[\/\\]+\Z//;
7163 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7164 return $Path;
7165}
7166
7167sub is_default_include_dir($)
7168{
7169 my $Dir = $_[0];
7170 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007171 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172}
7173
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007174sub identifyHeader($$)
7175{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007177 if(not $Header) {
7178 return "";
7179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007180 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007181 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7182 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007183 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007184 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185}
7186
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007187sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007188{ # search for header by absolute path, relative path or name
7189 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007190 if(-f $Header)
7191 { # it's relative or absolute path
7192 return get_abs_path($Header);
7193 }
7194 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7195 and my $HeaderDir = find_in_defaults($Header))
7196 { # search for libc headers in the /usr/include
7197 # for non-libc target library before searching
7198 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007199 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007200 }
7201 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7202 { # search in the target library paths
7203 return $Path;
7204 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007205 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206 { # search in the internal GCC include paths
7207 return $DefaultGccHeader{$Header};
7208 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007209 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007210 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007211 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007212 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007213 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007214 { # search in the default G++ include paths
7215 return $DefaultCppHeader{$Header};
7216 }
7217 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7218 { # search everywhere in the system
7219 return $AnyPath;
7220 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007221 elsif($OSgroup eq "macos")
7222 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7223 if(my $Dir = get_dirname($Header))
7224 {
7225 my $RelPath = "Headers\/".get_filename($Header);
7226 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007227 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007228 }
7229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007231 # cannot find anything
7232 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233}
7234
7235sub getLocation($)
7236{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007237 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7238 {
7239 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007240 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007242 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007243 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244}
7245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007246sub getNameByInfo($)
7247{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007248 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007249 {
7250 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7251 {
7252 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7253 {
7254 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7255 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007256 my $Str = $1;
7257 if($CppMode{$Version}
7258 and $Str=~/\Ac99_(.+)\Z/)
7259 {
7260 if($CppKeywords_A{$1}) {
7261 $Str=$1;
7262 }
7263 }
7264 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007265 }
7266 }
7267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007268 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007269 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007270}
7271
7272sub getTreeStr($)
7273{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007274 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007275 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007276 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7277 {
7278 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007279 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007280 and $Str=~/\Ac99_(.+)\Z/)
7281 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007282 if($CppKeywords_A{$1}) {
7283 $Str=$1;
7284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007286 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007288 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007289 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007290}
7291
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007292sub getFuncShortName($)
7293{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007294 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007295 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007296 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007298 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007299 {
7300 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7301 {
7302 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7303 return "operator ".$RName;
7304 }
7305 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007306 }
7307 else
7308 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007309 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7310 {
7311 if(my $Ind = $Operator_Indication{$1}) {
7312 return "operator".$Ind;
7313 }
7314 elsif(not $UnknownOperator{$1})
7315 {
7316 printMsg("WARNING", "unknown operator $1");
7317 $UnknownOperator{$1} = 1;
7318 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007319 }
7320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 }
7322 else
7323 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007324 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7325 return getTreeStr($1);
7326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327 }
7328 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007329 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007330}
7331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007332sub getFuncReturn($)
7333{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007334 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7335 {
7336 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7337 {
7338 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7339 return $1;
7340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341 }
7342 }
7343 return "";
7344}
7345
7346sub getFuncOrig($)
7347{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007348 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7349 {
7350 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7351 return $1;
7352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007353 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007354 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007355}
7356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007357sub unmangleArray(@)
7358{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007359 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007360 { # MSVC mangling
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007361 if(defined $DisabledMSVCUnmangling) {
7362 return @_;
7363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364 my $UndNameCmd = get_CmdPath("undname");
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007365 if(not $UndNameCmd)
7366 {
7367 if($OSgroup eq "windows") {
7368 exitStatus("Not_Found", "can't find \"undname\"");
7369 }
7370 elsif(not defined $DisabledMSVCUnmangling)
7371 {
7372 printMsg("WARNING", "can't find \"undname\", disable MSVC unmangling");
7373 $DisabledMSVCUnmangling = 1;
7374 return @_;
7375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007376 }
7377 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007378 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379 }
7380 else
7381 { # GCC mangling
7382 my $CppFiltCmd = get_CmdPath("c++filt");
7383 if(not $CppFiltCmd) {
7384 exitStatus("Not_Found", "can't find c++filt in PATH");
7385 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007386 if(not defined $CPPFILT_SUPPORT_FILE)
7387 {
7388 my $Info = `$CppFiltCmd -h 2>&1`;
7389 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7390 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007391 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007392 if($CPPFILT_SUPPORT_FILE)
7393 { # new versions of c++filt can take a file
7394 if($#_>$MAX_CPPFILT_FILE_SIZE)
7395 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7396 # this is fixed in the oncoming version of Binutils
7397 my @Half = splice(@_, 0, ($#_+1)/2);
7398 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007400 else
7401 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007402 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7403 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7404 if($?==139)
7405 { # segmentation fault
7406 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7407 }
7408 return split(/\n/, $Res);
7409 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 }
7411 else
7412 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007413 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7414 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 my @Half = splice(@_, 0, ($#_+1)/2);
7416 return (unmangleArray(@Half), unmangleArray(@_))
7417 }
7418 else
7419 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007421 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7422 if($?==139)
7423 { # segmentation fault
7424 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7425 }
7426 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007427 }
7428 }
7429 }
7430}
7431
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007432sub get_ChargeLevel($$)
7433{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007434 my ($Symbol, $LibVersion) = @_;
7435 return "" if($Symbol!~/\A(_Z|\?)/);
7436 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7437 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007439 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007440 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007441 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007442 return "[in-charge]";
7443 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007444 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007445 return "[not-in-charge]";
7446 }
7447 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007448 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007450 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451 return "[in-charge]";
7452 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007453 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007454 return "[not-in-charge]";
7455 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007456 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 return "[in-charge-deleting]";
7458 }
7459 }
7460 }
7461 else
7462 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007463 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007464 return "[in-charge]";
7465 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007466 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007467 return "[not-in-charge]";
7468 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007469 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 return "[in-charge]";
7471 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007472 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 return "[not-in-charge]";
7474 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007475 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 return "[in-charge-deleting]";
7477 }
7478 }
7479 return "";
7480}
7481
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007482sub get_Signature_M($$)
7483{
7484 my ($Symbol, $LibVersion) = @_;
7485 my $Signature_M = $tr_name{$Symbol};
7486 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7487 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007488 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007489 }
7490 return $Signature_M;
7491}
7492
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007493sub get_Signature($$)
7494{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007495 my ($Symbol, $LibVersion) = @_;
7496 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7497 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007499 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007500 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007501
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007502 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007503
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007504 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007505 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007506 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7507 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007508 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7509 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007510
7511 if(index($Symbol, "_ZTV")==0) {
7512 return "vtable for $ClassName [data]";
7513 }
7514
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007515 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007516 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7517 $Signature .= "~";
7518 }
7519 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007522 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
7524 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007525 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007526 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007527 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7528 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007529 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007530 else
7531 {
7532 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007533 }
7534 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007535 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007537 if($Pos eq "") {
7538 next;
7539 }
7540
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007541 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007542 if(not $ParamTypeId) {
7543 next;
7544 }
7545
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007546 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 if(not $ParamTypeName) {
7548 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7549 }
7550 foreach my $Typedef (keys(%ChangedTypedef))
7551 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007552 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7553 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007556 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7557 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007558 if($ParamName eq "this"
7559 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007560 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007561 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007562 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007563 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007564 }
7565 else {
7566 push(@ParamArray, $ParamTypeName);
7567 }
7568 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007569 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7570 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007571 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007572 }
7573 else
7574 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007575 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007576 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007577 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007579 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007580 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7581 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007582 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007583 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007584 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7585 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007586 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007587 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007588 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7589 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007590 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007591 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592 }
7593 }
7594 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007595 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007596 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 }
7598 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007599 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007600 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007601 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007602}
7603
7604sub create_member_decl($$)
7605{
7606 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007607 if($TName=~/\([\*]+\)/)
7608 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7610 return $TName;
7611 }
7612 else
7613 {
7614 my @ArraySizes = ();
7615 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7616 push(@ArraySizes, $1);
7617 }
7618 return $TName." ".$Member.join("", @ArraySizes);
7619 }
7620}
7621
7622sub getFuncType($)
7623{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007624 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7625 {
7626 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7627 {
7628 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7629 {
7630 if($Type eq "method_type") {
7631 return "Method";
7632 }
7633 elsif($Type eq "function_type") {
7634 return "Function";
7635 }
7636 else {
7637 return "Other";
7638 }
7639 }
7640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007641 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007642 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007643}
7644
7645sub getFuncTypeId($)
7646{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007647 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7648 {
7649 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7650 return $1;
7651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007652 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007653 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654}
7655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007656sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007657{ # "._N" or "$_N" in older GCC versions
7658 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007659}
7660
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007661sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007662{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007663 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7664 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007665 }
7666
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007667 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007668
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007669 if($_[1] ne "S")
7670 {
7671 $N=~s/\A[ ]+//g;
7672 $N=~s/[ ]+\Z//g;
7673 $N=~s/[ ]{2,}/ /g;
7674 }
7675
7676 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007677
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007678 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7679
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007680 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007681
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007682 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7683 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007684
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007685 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007686
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007687 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007688
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007689 if($_[1] eq "S")
7690 {
7691 if(index($N, "operator")!=-1) {
7692 $N=~s/\b(operator[ ]*)> >/$1>>/;
7693 }
7694 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007695
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007696 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007697
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007698 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007699}
7700
7701sub get_HeaderDeps($$)
7702{
7703 my ($AbsPath, $LibVersion) = @_;
7704 return () if(not $AbsPath or not $LibVersion);
7705 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7706 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7707 }
7708 my %IncDir = ();
7709 detect_recursive_includes($AbsPath, $LibVersion);
7710 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7711 {
7712 next if(not $HeaderPath);
7713 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7714 my $Dir = get_dirname($HeaderPath);
7715 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7716 {
7717 my $Dep = $Dir;
7718 if($Prefix)
7719 {
7720 if($OSgroup eq "windows")
7721 { # case insensitive seach on windows
7722 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7723 next;
7724 }
7725 }
7726 elsif($OSgroup eq "macos")
7727 { # seach in frameworks
7728 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7729 {
7730 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7731 {# frameworks
7732 my ($HFramework, $HName) = ($1, $2);
7733 $Dep = $HFramework;
7734 }
7735 else
7736 {# mismatch
7737 next;
7738 }
7739 }
7740 }
7741 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7742 { # Linux, FreeBSD
7743 next;
7744 }
7745 }
7746 if(not $Dep)
7747 { # nothing to include
7748 next;
7749 }
7750 if(is_default_include_dir($Dep))
7751 { # included by the compiler
7752 next;
7753 }
7754 if(get_depth($Dep)==1)
7755 { # too short
7756 next;
7757 }
7758 if(isLibcDir($Dep))
7759 { # do NOT include /usr/include/{sys,bits}
7760 next;
7761 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007762 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007763 }
7764 }
7765 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7766 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7767}
7768
7769sub sortIncPaths($$)
7770{
7771 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007772 if(not $ArrRef or $#{$ArrRef}<0) {
7773 return $ArrRef;
7774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007775 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7776 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007777 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007778 return $ArrRef;
7779}
7780
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007781sub sortDeps($$$)
7782{
7783 if($Header_Dependency{$_[2]}{$_[0]}
7784 and not $Header_Dependency{$_[2]}{$_[1]}) {
7785 return 1;
7786 }
7787 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7788 and $Header_Dependency{$_[2]}{$_[1]}) {
7789 return -1;
7790 }
7791 return 0;
7792}
7793
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007794sub join_P($$)
7795{
7796 my $S = "/";
7797 if($OSgroup eq "windows") {
7798 $S = "\\";
7799 }
7800 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007801}
7802
7803sub get_namespace_additions($)
7804{
7805 my $NameSpaces = $_[0];
7806 my ($Additions, $AddNameSpaceId) = ("", 1);
7807 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7808 {
7809 next if($SkipNameSpaces{$Version}{$NS});
7810 next if(not $NS or $NameSpaces->{$NS}==-1);
7811 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7812 next if($NS=~/\A__/i);
7813 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007814 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007815 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7816 my @NS_Parts = split(/::/, $NS);
7817 next if($#NS_Parts==-1);
7818 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7819 foreach my $NS_Part (@NS_Parts)
7820 {
7821 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7822 $TypeDecl_Suffix .= "}";
7823 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007824 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007825 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7826 $Additions.=" $TypeDecl\n $FuncDecl\n";
7827 $AddNameSpaceId+=1;
7828 }
7829 return $Additions;
7830}
7831
7832sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007833{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007834 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007835 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007836 if($Fmt eq "windows")
7837 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007838 $Path=~s/\//\\/g;
7839 $Path=lc($Path);
7840 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007841 else
7842 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007843 $Path=~s/\\/\//g;
7844 }
7845 return $Path;
7846}
7847
7848sub inc_opt($$)
7849{
7850 my ($Path, $Style) = @_;
7851 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007852 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007853 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007854 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007855 return "-I\"".path_format($Path, "unix")."\"";
7856 }
7857 elsif($OSgroup eq "macos"
7858 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007859 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007860 return "-F".esc(get_dirname($Path));
7861 }
7862 else {
7863 return "-I".esc($Path);
7864 }
7865 }
7866 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007867 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007868 }
7869 return "";
7870}
7871
7872sub platformSpecs($)
7873{
7874 my $LibVersion = $_[0];
7875 my $Arch = getArch($LibVersion);
7876 if($OStarget eq "symbian")
7877 { # options for GCCE compiler
7878 my %Symbian_Opts = map {$_=>1} (
7879 "-D__GCCE__",
7880 "-DUNICODE",
7881 "-fexceptions",
7882 "-D__SYMBIAN32__",
7883 "-D__MARM_INTERWORK__",
7884 "-D_UNICODE",
7885 "-D__S60_50__",
7886 "-D__S60_3X__",
7887 "-D__SERIES60_3X__",
7888 "-D__EPOC32__",
7889 "-D__MARM__",
7890 "-D__EABI__",
7891 "-D__MARM_ARMV5__",
7892 "-D__SUPPORT_CPP_EXCEPTIONS__",
7893 "-march=armv5t",
7894 "-mapcs",
7895 "-mthumb-interwork",
7896 "-DEKA2",
7897 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7898 );
7899 return join(" ", keys(%Symbian_Opts));
7900 }
7901 elsif($OSgroup eq "windows"
7902 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7903 { # add options to MinGW compiler
7904 # to simulate the MSVC compiler
7905 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007906 "-D__unaligned=\" \"",
7907 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007908 "-D_WIN32",
7909 "-D_STDCALL_SUPPORTED",
7910 "-D__int64=\"long long\"",
7911 "-D__int32=int",
7912 "-D__int16=short",
7913 "-D__int8=char",
7914 "-D__possibly_notnullterminated=\" \"",
7915 "-D__nullterminated=\" \"",
7916 "-D__nullnullterminated=\" \"",
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007917 "-D__assume=\" \"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007918 "-D__w64=\" \"",
7919 "-D__ptr32=\" \"",
7920 "-D__ptr64=\" \"",
7921 "-D__forceinline=inline",
7922 "-D__inline=inline",
7923 "-D__uuidof(x)=IID()",
7924 "-D__try=",
7925 "-D__except(x)=",
7926 "-D__declspec(x)=__attribute__((x))",
7927 "-D__pragma(x)=",
7928 "-D_inline=inline",
7929 "-D__forceinline=__inline",
7930 "-D__stdcall=__attribute__((__stdcall__))",
7931 "-D__cdecl=__attribute__((__cdecl__))",
7932 "-D__fastcall=__attribute__((__fastcall__))",
7933 "-D__thiscall=__attribute__((__thiscall__))",
7934 "-D_stdcall=__attribute__((__stdcall__))",
7935 "-D_cdecl=__attribute__((__cdecl__))",
7936 "-D_fastcall=__attribute__((__fastcall__))",
7937 "-D_thiscall=__attribute__((__thiscall__))",
7938 "-DSHSTDAPI_(x)=x",
7939 "-D_MSC_EXTENSIONS",
7940 "-DSECURITY_WIN32",
7941 "-D_MSC_VER=1500",
7942 "-D_USE_DECLSPECS_FOR_SAL",
7943 "-D__noop=\" \"",
7944 "-DDECLSPEC_DEPRECATED=\" \"",
7945 "-D__builtin_alignof(x)=__alignof__(x)",
7946 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007947 if($Arch eq "x86")
7948 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007949 $MinGW_Opts{"-D_X86_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007950 $MinGW_Opts{"-D_M_IX86=300"}=1;
7951 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007952 elsif($Arch eq "x86_64")
7953 {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007954 $MinGW_Opts{"-D_AMD64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007955 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007956 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007957 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007958 elsif($Arch eq "ia64")
7959 {
7960 $MinGW_Opts{"-D_IA64_=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007961 $MinGW_Opts{"-D_M_IA64=300"}=1;
7962 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03007963 return join(" ", sort keys(%MinGW_Opts));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007964 }
7965 return "";
7966}
7967
7968my %C_Structure = map {$_=>1} (
7969# FIXME: Can't separate union and struct data types before dumping,
7970# so it sometimes cause compilation errors for unknown reason
7971# when trying to declare TYPE* tmp_add_class_N
7972# This is a list of such structures + list of other C structures
7973 "sigval",
7974 "sigevent",
7975 "sigaction",
7976 "sigvec",
7977 "sigstack",
7978 "timeval",
7979 "timezone",
7980 "rusage",
7981 "rlimit",
7982 "wait",
7983 "flock",
7984 "stat",
7985 "_stat",
7986 "stat32",
7987 "_stat32",
7988 "stat64",
7989 "_stat64",
7990 "_stati64",
7991 "if_nameindex",
7992 "usb_device",
7993 "sigaltstack",
7994 "sysinfo",
7995 "timeLocale",
7996 "tcp_debug",
7997 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007998 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007999 "timespec",
8000 "random_data",
8001 "drand48_data",
8002 "_IO_marker",
8003 "_IO_FILE",
8004 "lconv",
8005 "sched_param",
8006 "tm",
8007 "itimerspec",
8008 "_pthread_cleanup_buffer",
8009 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008010 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008011 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008012 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008013 "sigcontext",
8014 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008015 # Mac
8016 "_timex",
8017 "_class_t",
8018 "_category_t",
8019 "_class_ro_t",
8020 "_protocol_t",
8021 "_message_ref_t",
8022 "_super_message_ref_t",
8023 "_ivar_t",
8024 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008025);
8026
8027sub getCompileCmd($$$)
8028{
8029 my ($Path, $Opt, $Inc) = @_;
8030 my $GccCall = $GCC_PATH;
8031 if($Opt) {
8032 $GccCall .= " ".$Opt;
8033 }
8034 $GccCall .= " -x ";
8035 if($OSgroup eq "macos") {
8036 $GccCall .= "objective-";
8037 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008038
8039 if($EMERGENCY_MODE_48)
8040 { # workaround for GCC 4.8 (C only)
8041 $GccCall .= "c++";
8042 }
8043 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008044 { # compile as "C++" header
8045 # to obtain complete dump using GCC 4.0
8046 $GccCall .= "c++-header";
8047 }
8048 else
8049 { # compile as "C++" source
8050 # GCC 3.3 cannot compile headers
8051 $GccCall .= "c++";
8052 }
8053 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008054 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008055 $GccCall .= " ".$Opts;
8056 }
8057 # allow extra qualifications
8058 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008059 $GccCall .= " -fpermissive";
8060 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008061 if($NoStdInc)
8062 {
8063 $GccCall .= " -nostdinc";
8064 $GccCall .= " -nostdinc++";
8065 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008066 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008067 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008068 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008069 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008070 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008071 if($Inc)
8072 { # include paths
8073 $GccCall .= " ".$Inc;
8074 }
8075 return $GccCall;
8076}
8077
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008078sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008079{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008080 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008081 my %HeaderElems = (
8082 # Types
8083 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008084 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008085 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8086 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008087 "time.h" => ["time_t"],
8088 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008089 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8090 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008091 "stdbool.h" => ["_Bool"],
8092 "rpc/xdr.h" => ["bool_t"],
8093 "in_systm.h" => ["n_long", "n_short"],
8094 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008095 "arpa/inet.h" => ["fw_src", "ip_src"],
8096 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008097 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008098 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008099 );
8100 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008101 foreach (keys(%HeaderElems))
8102 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008103 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008104 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008105 }
8106 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008107 my %Types = ();
8108 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8109 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008110 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008111 }
8112 if(keys(%Types))
8113 {
8114 my %AddHeaders = ();
8115 foreach my $Type (keys(%Types))
8116 {
8117 if(my $Header = $AutoPreamble{$Type})
8118 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008119 if(my $Path = identifyHeader($Header, $LibVersion))
8120 {
8121 if(skipHeader($Path, $LibVersion)) {
8122 next;
8123 }
8124 $Path = path_format($Path, $OSgroup);
8125 $AddHeaders{$Path}{"Type"} = $Type;
8126 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008127 }
8128 }
8129 }
8130 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008131 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008132 }
8133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008134 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008135}
8136
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008137sub checkCTags($)
8138{
8139 my $Path = $_[0];
8140 if(not $Path) {
8141 return;
8142 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008143 my $CTags = undef;
8144
8145 if($OSgroup eq "bsd")
8146 { # use ectags on BSD
8147 $CTags = get_CmdPath("ectags");
8148 if(not $CTags) {
8149 printMsg("WARNING", "can't find \'ectags\' program");
8150 }
8151 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008152 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008153 $CTags = get_CmdPath("ctags");
8154 }
8155 if(not $CTags)
8156 {
8157 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008158 return;
8159 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008160
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008161 if($OSgroup ne "linux")
8162 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008163 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8164 if($Info!~/exuberant/i)
8165 {
8166 printMsg("WARNING", "incompatible version of \'ctags\' program");
8167 return;
8168 }
8169 }
8170
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008171 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008172 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008173 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008174 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008175 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008176 open(CTAGS, "<", $Out);
8177 while(my $Line = <CTAGS>)
8178 {
8179 chomp($Line);
8180 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008181 if(defined $Intrinsic_Keywords{$Name})
8182 { # noise
8183 next;
8184 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008185 if($Type eq "n")
8186 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008187 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008188 next;
8189 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008190 if(index($Scpe, "struct:")==0) {
8191 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008192 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008193 if(index($Scpe, "namespace:")==0)
8194 {
8195 if($Scpe=~s/\Anamespace://) {
8196 $Name = $Scpe."::".$Name;
8197 }
8198 }
8199 $TUnit_NameSpaces{$Version}{$Name} = 1;
8200 }
8201 elsif($Type eq "p")
8202 {
8203 if(not $Scpe or index($Scpe, "namespace:")==0) {
8204 $TUnit_Funcs{$Version}{$Name} = 1;
8205 }
8206 }
8207 elsif($Type eq "x")
8208 {
8209 if(not $Scpe or index($Scpe, "namespace:")==0) {
8210 $TUnit_Vars{$Version}{$Name} = 1;
8211 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008212 }
8213 }
8214 close(CTAGS);
8215}
8216
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008217sub preChange($$)
8218{
8219 my ($HeaderPath, $IncStr) = @_;
8220
8221 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8222 my $Content = undef;
8223
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008224 if(not defined $MinGWCompat and $OStarget eq "windows"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008225 and get_dumpmachine($GCC_PATH)=~/mingw/i
8226 and $MinGWMode{$Version}!=-1)
8227 { # modify headers to compile by MinGW
8228 if(not $Content)
8229 { # preprocessing
8230 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8231 }
8232 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8233 { # __asm { ... }
8234 $MinGWMode{$Version}=1;
8235 }
8236 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8237 { # comments after preprocessing
8238 $MinGWMode{$Version}=1;
8239 }
8240 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8241 { # 0xffui8
8242 $MinGWMode{$Version}=1;
8243 }
8244
8245 if($MinGWMode{$Version}) {
8246 printMsg("INFO", "Using MinGW compatibility mode");
8247 }
8248 }
8249
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008250 if(defined $CxxIncompat and ($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8251 and $CppMode{$Version}!=-1 and not $CPP_HEADERS)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008252 { # rename C++ keywords in C code
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008253 printMsg("INFO", "Checking the code for C++ keywords");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008254 if(not $Content)
8255 { # preprocessing
8256 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8257 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008258
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008259 my $RegExp_C = join("|", keys(%CppKeywords_C));
8260 my $RegExp_F = join("|", keys(%CppKeywords_F));
8261 my $RegExp_O = join("|", keys(%CppKeywords_O));
8262
8263 my $Detected = undef;
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008264 my $Sentence_O = undef;
8265 my $Sentence_N = undef;
8266 my $Regex = undef;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008267
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008268 $Regex = qr/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/;
8269 while($Content=~/$Regex/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008270 { # MATCH:
8271 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008272 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008273 # unsigned private: 8;
8274 # DO NOT MATCH:
8275 # #pragma GCC visibility push(default)
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008276 $Sentence_O = "$1$2$3$4";
8277 $Sentence_N = "$1$2c99_$3$4";
8278
8279 if($Sentence_O=~/\s+decltype\(/)
8280 { # C++
8281 # decltype(nullptr)
8282 last;
8283 }
8284 else
8285 {
8286 $Content=~s/$Regex/$Sentence_N/g;
8287 $CppMode{$Version} = 1;
8288 if(not defined $Detected) {
8289 $Detected = $Sentence_O;
8290 }
8291 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008292 }
8293 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8294 { # MATCH:
8295 # int delete(...);
8296 # int explicit(...);
8297 # DO NOT MATCH:
8298 # void operator delete(...)
8299 $CppMode{$Version} = 1;
8300 $Detected = "$1$2$3" if(not defined $Detected);
8301 }
8302 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8303 { # MATCH:
8304 # int bool;
8305 # DO NOT MATCH:
8306 # bool X;
8307 # return *this;
8308 # throw;
8309 $CppMode{$Version} = 1;
8310 $Detected = "$1$2$3" if(not defined $Detected);
8311 }
8312 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8313 { # MATCH:
8314 # int operator(...);
8315 # DO NOT MATCH:
8316 # int operator()(...);
8317 $CppMode{$Version} = 1;
8318 $Detected = "$1$2$3" if(not defined $Detected);
8319 }
8320 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8321 { # MATCH:
8322 # int foo(int operator);
8323 # int foo(int operator, int other);
8324 # DO NOT MATCH:
8325 # int operator,(...);
8326 $CppMode{$Version} = 1;
8327 $Detected = "$1$2$3" if(not defined $Detected);
8328 }
8329 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8330 { # MATCH:
8331 # int foo(gboolean *bool);
8332 # DO NOT MATCH:
8333 # void setTabEnabled(int index, bool);
8334 $CppMode{$Version} = 1;
8335 $Detected = "$1$2$3" if(not defined $Detected);
8336 }
8337 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8338 { # MATCH:
8339 # int foo(int* this);
8340 # int bar(int this);
8341 # int baz(int throw);
8342 # DO NOT MATCH:
8343 # foo(X, this);
8344 $CppMode{$Version} = 1;
8345 $Detected = "$1$2$3$4" if(not defined $Detected);
8346 }
8347 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8348 { # MATCH:
8349 # struct template {...};
8350 # extern template foo(...);
8351 $CppMode{$Version} = 1;
8352 $Detected = "$1$2" if(not defined $Detected);
8353 }
8354
8355 if($CppMode{$Version} == 1)
8356 {
8357 if($Debug)
8358 {
8359 $Detected=~s/\A\s+//g;
8360 printMsg("INFO", "Detected code: \"$Detected\"");
8361 }
8362 }
8363
8364 # remove typedef enum NAME NAME;
8365 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8366 my $N = 0;
8367 while($N<=$#FwdTypedefs-1)
8368 {
8369 my $S = $FwdTypedefs[$N];
8370 if($S eq $FwdTypedefs[$N+1])
8371 {
8372 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008373 $CppMode{$Version} = 1;
8374
8375 if($Debug) {
8376 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8377 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008378 }
8379 $N+=2;
8380 }
8381
8382 if($CppMode{$Version}==1) {
8383 printMsg("INFO", "Using C++ compatibility mode");
8384 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008385 else {
8386 printMsg("INFO", "C++ keywords in the C code are not found");
8387 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008388 }
8389
8390 if($CppMode{$Version}==1
8391 or $MinGWMode{$Version}==1)
8392 {
8393 my $IPath = $TMP_DIR."/dump$Version.i";
8394 writeFile($IPath, $Content);
8395 return $IPath;
8396 }
8397
8398 return undef;
8399}
8400
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008401sub getDump()
8402{
8403 if(not $GCC_PATH) {
8404 exitStatus("Error", "internal error - GCC path is not set");
8405 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008406
8407 my @Headers = keys(%{$Registered_Headers{$Version}});
8408 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8409
8410 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8411
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008412 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008413 my $HeaderPath = $TmpHeaderPath;
8414
8415 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008416 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008417 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8418 {
8419 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008420 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008421 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008422 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008423 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8424 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008425 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008426 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008427 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008428 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8429 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008431 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008432 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008434 if($ExtraInfo)
8435 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008436 if($IncludeString) {
8437 writeFile($ExtraInfo."/include-string", $IncludeString);
8438 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008439 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8440 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008441
8442 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8443 {
8444 my $REDIR = "";
8445 foreach my $P1 (sort @Redirects) {
8446 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8447 }
8448 writeFile($ExtraInfo."/include-redirect", $REDIR);
8449 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008450 }
8451
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008452 if(not keys(%{$TargetHeaders{$Version}}))
8453 { # Target headers
8454 addTargetHeaders($Version);
8455 }
8456
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008457 # clean memory
8458 %RecursiveIncludes = ();
8459 %Header_Include_Prefix = ();
8460 %Header_Includes = ();
8461
8462 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008463 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008464 delete($Cache{"detect_header_includes"});
8465 delete($Cache{"selectSystemHeader"});
8466
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008467 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008468 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8469 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008470
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008471 if($ExtraInfo)
8472 { # extra information for other tools
8473 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8474 }
8475
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008476 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008477 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008478 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008479
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008480 if($COMMON_LANGUAGE{$Version} eq "C++") {
8481 checkCTags($Pre);
8482 }
8483
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008484 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8485 { # try to correct the preprocessor output
8486 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008487 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008488
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008489 if($COMMON_LANGUAGE{$Version} eq "C++")
8490 { # add classes and namespaces to the dump
8491 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008492 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008493 or $MinGWMode{$Version}==1) {
8494 $CHdump .= " -fpreprocessed";
8495 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008496 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008497 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008498 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008499 chdir($ORIG_DIR);
8500 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8501 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008502 my $Content = readFile($ClassDump);
8503 foreach my $ClassInfo (split(/\n\n/, $Content))
8504 {
8505 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8506 {
8507 my $CName = $1;
8508 next if($CName=~/\A(__|_objc_|_opaque_)/);
8509 $TUnit_NameSpaces{$Version}{$CName} = -1;
8510 if($CName=~/\A[\w:]+\Z/)
8511 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008512 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008513 }
8514 if($CName=~/(\w[\w:]*)::/)
8515 { # namespaces
8516 my $NS = $1;
8517 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8518 $TUnit_NameSpaces{$Version}{$NS} = 1;
8519 }
8520 }
8521 }
8522 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8523 { # read v-tables (advanced approach)
8524 my ($CName, $VTable) = ($1, $2);
8525 $ClassVTable_Content{$Version}{$CName} = $VTable;
8526 }
8527 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008528 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8529 { # add user-defined namespaces
8530 $TUnit_NameSpaces{$Version}{$NS} = 1;
8531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008532 if($Debug)
8533 { # debug mode
8534 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008535 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008536 }
8537 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008538 }
8539
8540 # add namespaces and classes
8541 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8542 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008543 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008544 }
8545 # some GCC versions don't include class methods to the TU dump by default
8546 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008547 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008548 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8549 {
8550 next if($C_Structure{$CName});
8551 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008552 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008553 if(not $Force and $GCC_44
8554 and $OSgroup eq "linux")
8555 { # optimization for linux with GCC >= 4.4
8556 # disable this code by -force option
8557 if(index($CName, "::")!=-1)
8558 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008559 next;
8560 }
8561 }
8562 else
8563 {
8564 if($CName=~/\A(.+)::[^:]+\Z/
8565 and $TUnit_Classes{$Version}{$1})
8566 { # classes inside other classes
8567 next;
8568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008569 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008570 if(defined $TUnit_Funcs{$Version}{$CName})
8571 { # the same name for a function and type
8572 next;
8573 }
8574 if(defined $TUnit_Vars{$Version}{$CName})
8575 { # the same name for a variable and type
8576 next;
8577 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008578 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8579 }
8580 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008581 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008582 }
8583 }
8584 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8585 # create TU dump
8586 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008587 if($UserLang eq "C") {
8588 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8589 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008590 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008591 or $MinGWMode{$Version}==1) {
8592 $TUdump .= " -fpreprocessed";
8593 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008594 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8596 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008597 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008598 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008599 if($?)
8600 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008601 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008602 { # try to recompile
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008603 # FIXME: handle errors and try to recompile
8604 if($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008605 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008606 { # add auto preamble headers and try again
8607 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008608 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008609 foreach my $Num (0 .. $#Headers)
8610 {
8611 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008612 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8613 {
8614 push_U($Include_Preamble{$Version}, $Path);
8615 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008616 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008617 }
8618 resetLogging($Version);
8619 $TMP_DIR = tempdir(CLEANUP=>1);
8620 return getDump();
8621 }
8622 elsif($Cpp0xMode{$Version}!=-1
8623 and ($Errors=~/\Q-std=c++0x\E/
8624 or $Errors=~/is not a class or namespace/))
8625 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008626 if(check_gcc($GCC_PATH, "4.6"))
8627 {
8628 $Cpp0xMode{$Version}=-1;
8629 printMsg("INFO", "Enabling c++0x mode");
8630 resetLogging($Version);
8631 $TMP_DIR = tempdir(CLEANUP=>1);
8632 $CompilerOptions{$Version} .= " -std=c++0x";
8633 return getDump();
8634 }
8635 else {
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008636 printMsg("WARNING", "Probably c++0x element detected");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008637 }
8638
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008639 }
Andrey Ponomarenko991da682016-09-07 19:09:50 +03008640 #elsif($MinGWMode{$Version}==1)
8641 #{ # disable MinGW mode and try again
8642 # $MinGWMode{$Version}=-1;
8643 # resetLogging($Version);
8644 # $TMP_DIR = tempdir(CLEANUP=>1);
8645 # return getDump();
8646 #}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008647 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008648 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008649 else {
8650 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008652 printMsg("ERROR", "some errors occurred when compiling headers");
8653 printErrorLog($Version);
8654 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008655 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656 }
8657 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008658 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008659 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008660
8661 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8662 return $TUs[0];
8663 }
8664 else
8665 {
8666 my $Msg = "can't compile header(s)";
8667 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8668 $Msg .= "\nDid you install G++?";
8669 }
8670 exitStatus("Cannot_Compile", $Msg);
8671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008672}
8673
8674sub cmd_file($)
8675{
8676 my $Path = $_[0];
8677 return "" if(not $Path or not -e $Path);
8678 if(my $CmdPath = get_CmdPath("file")) {
8679 return `$CmdPath -b \"$Path\"`;
8680 }
8681 return "";
8682}
8683
8684sub getIncString($$)
8685{
8686 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008687 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008688 my $String = "";
8689 foreach (@{$ArrRef}) {
8690 $String .= " ".inc_opt($_, $Style);
8691 }
8692 return $String;
8693}
8694
8695sub getIncPaths(@)
8696{
8697 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008698 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008699 if($INC_PATH_AUTODETECT{$Version})
8700 { # auto-detecting dependencies
8701 my %Includes = ();
8702 foreach my $HPath (@HeaderPaths)
8703 {
8704 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8705 {
8706 if($Skip_Include_Paths{$Version}{$Dir}) {
8707 next;
8708 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008709 if($SystemRoot)
8710 {
8711 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8712 next;
8713 }
8714 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008715 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008716 }
8717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008718 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008719 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 }
8721 }
8722 else
8723 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008724 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008725 }
8726 return \@IncPaths;
8727}
8728
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008729sub push_U($@)
8730{ # push unique
8731 if(my $Array = shift @_)
8732 {
8733 if(@_)
8734 {
8735 my %Exist = map {$_=>1} @{$Array};
8736 foreach my $Elem (@_)
8737 {
8738 if(not defined $Exist{$Elem})
8739 {
8740 push(@{$Array}, $Elem);
8741 $Exist{$Elem} = 1;
8742 }
8743 }
8744 }
8745 }
8746}
8747
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008748sub callPreprocessor($$$)
8749{
8750 my ($Path, $Inc, $LibVersion) = @_;
8751 return "" if(not $Path or not -f $Path);
8752 my $IncludeString=$Inc;
8753 if(not $Inc) {
8754 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8755 }
8756 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008757 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008758 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008759 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008760}
8761
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008762sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008763{ # native "find" is much faster than File::Find (~6x)
8764 # also the File::Find doesn't support --maxdepth N option
8765 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008766 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008767 return () if(not $Path or not -e $Path);
8768 if($OSgroup eq "windows")
8769 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008770 $Path = get_abs_path($Path);
8771 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008772 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008773 if($MaxDepth!=1) {
8774 $Cmd .= " /S";
8775 }
8776 if($Type eq "d") {
8777 $Cmd .= " /AD";
8778 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008779 elsif($Type eq "f") {
8780 $Cmd .= " /A-D";
8781 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008782 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008783 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008784 {
8785 if(not $UseRegex)
8786 { # FIXME: how to search file names in MS shell?
8787 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008788 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008789 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008790 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008791 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008792 }
8793 my @AbsPaths = ();
8794 foreach my $File (@Files)
8795 {
8796 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008797 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008798 }
8799 if($Type eq "f" and not -f $File)
8800 { # skip dirs
8801 next;
8802 }
8803 push(@AbsPaths, path_format($File, $OSgroup));
8804 }
8805 if($Type eq "d") {
8806 push(@AbsPaths, $Path);
8807 }
8808 return @AbsPaths;
8809 }
8810 else
8811 {
8812 my $FindCmd = get_CmdPath("find");
8813 if(not $FindCmd) {
8814 exitStatus("Not_Found", "can't find a \"find\" command");
8815 }
8816 $Path = get_abs_path($Path);
8817 if(-d $Path and -l $Path
8818 and $Path!~/\/\Z/)
8819 { # for directories that are symlinks
8820 $Path.="/";
8821 }
8822 my $Cmd = $FindCmd." \"$Path\"";
8823 if($MaxDepth) {
8824 $Cmd .= " -maxdepth $MaxDepth";
8825 }
8826 if($Type) {
8827 $Cmd .= " -type $Type";
8828 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008829 if($Name and not $UseRegex)
8830 { # wildcards
8831 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008833 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008834 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008835 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008837 my @Files = split(/\n/, $Res);
8838 if($Name and $UseRegex)
8839 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008840 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008841 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008842 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008843 }
8844}
8845
8846sub unpackDump($)
8847{
8848 my $Path = $_[0];
8849 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008851 $Path = get_abs_path($Path);
8852 $Path = path_format($Path, $OSgroup);
8853 my ($Dir, $FileName) = separate_path($Path);
8854 my $UnpackDir = $TMP_DIR."/unpack";
8855 rmtree($UnpackDir);
8856 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008857
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008858 if($FileName=~s/\Q.zip\E\Z//g)
8859 { # *.zip
8860 my $UnzipCmd = get_CmdPath("unzip");
8861 if(not $UnzipCmd) {
8862 exitStatus("Not_Found", "can't find \"unzip\" command");
8863 }
8864 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008865 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008866 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008867 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008868 }
8869 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008870 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008871 if(not @Contents) {
8872 exitStatus("Error", "can't extract \'$Path\'");
8873 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008874 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008876 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008877 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008878 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 if($OSgroup eq "windows")
8880 { # -xvzf option is not implemented in tar.exe (2003)
8881 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8882 my $TarCmd = get_CmdPath("tar");
8883 if(not $TarCmd) {
8884 exitStatus("Not_Found", "can't find \"tar\" command");
8885 }
8886 my $GzipCmd = get_CmdPath("gzip");
8887 if(not $GzipCmd) {
8888 exitStatus("Not_Found", "can't find \"gzip\" command");
8889 }
8890 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008891 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 if($?) {
8893 exitStatus("Error", "can't extract \'$Path\'");
8894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008895 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008897 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008898 }
8899 chdir($ORIG_DIR);
8900 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008901 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008902 if(not @Contents) {
8903 exitStatus("Error", "can't extract \'$Path\'");
8904 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008905 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008906 }
8907 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008908 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 my $TarCmd = get_CmdPath("tar");
8910 if(not $TarCmd) {
8911 exitStatus("Not_Found", "can't find \"tar\" command");
8912 }
8913 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008914 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008916 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 }
8918 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008919 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008920 if(not @Contents) {
8921 exitStatus("Error", "can't extract \'$Path\'");
8922 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008923 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008924 }
8925 }
8926}
8927
8928sub createArchive($$)
8929{
8930 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008931 if(not $To) {
8932 $To = ".";
8933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008934 if(not $Path or not -e $Path
8935 or not -d $To) {
8936 return "";
8937 }
8938 my ($From, $Name) = separate_path($Path);
8939 if($OSgroup eq "windows")
8940 { # *.zip
8941 my $ZipCmd = get_CmdPath("zip");
8942 if(not $ZipCmd) {
8943 exitStatus("Not_Found", "can't find \"zip\"");
8944 }
8945 my $Pkg = $To."/".$Name.".zip";
8946 unlink($Pkg);
8947 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008948 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008949 if($?)
8950 { # cannot allocate memory (or other problems with "zip")
8951 unlink($Path);
8952 exitStatus("Error", "can't pack the ABI dump: ".$!);
8953 }
8954 chdir($ORIG_DIR);
8955 unlink($Path);
8956 return $Pkg;
8957 }
8958 else
8959 { # *.tar.gz
8960 my $TarCmd = get_CmdPath("tar");
8961 if(not $TarCmd) {
8962 exitStatus("Not_Found", "can't find \"tar\"");
8963 }
8964 my $GzipCmd = get_CmdPath("gzip");
8965 if(not $GzipCmd) {
8966 exitStatus("Not_Found", "can't find \"gzip\"");
8967 }
8968 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8969 unlink($Pkg);
8970 chdir($From);
8971 system($TarCmd, "-czf", $Pkg, $Name);
8972 if($?)
8973 { # cannot allocate memory (or other problems with "tar")
8974 unlink($Path);
8975 exitStatus("Error", "can't pack the ABI dump: ".$!);
8976 }
8977 chdir($ORIG_DIR);
8978 unlink($Path);
8979 return $To."/".$Name.".tar.gz";
8980 }
8981}
8982
8983sub is_header_file($)
8984{
8985 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8986 return $_[0];
8987 }
8988 return 0;
8989}
8990
8991sub is_not_header($)
8992{
8993 if($_[0]=~/\.\w+\Z/
8994 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8995 return 1;
8996 }
8997 return 0;
8998}
8999
9000sub is_header($$$)
9001{
9002 my ($Header, $UserDefined, $LibVersion) = @_;
9003 return 0 if(-d $Header);
9004 if(-f $Header) {
9005 $Header = get_abs_path($Header);
9006 }
9007 else
9008 {
9009 if(is_abs($Header))
9010 { # incorrect absolute path
9011 return 0;
9012 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009013 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009014 $Header = $HPath;
9015 }
9016 else
9017 { # can't find header
9018 return 0;
9019 }
9020 }
9021 if($Header=~/\.\w+\Z/)
9022 { # have an extension
9023 return is_header_file($Header);
9024 }
9025 else
9026 {
9027 if($UserDefined==2)
9028 { # specified on the command line
9029 if(cmd_file($Header)!~/HTML|XML/i) {
9030 return $Header;
9031 }
9032 }
9033 elsif($UserDefined)
9034 { # specified in the XML-descriptor
9035 # header file without an extension
9036 return $Header;
9037 }
9038 else
9039 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009040 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009041 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009042 { # !~/HTML|XML|shared|dynamic/i
9043 return $Header;
9044 }
9045 }
9046 }
9047 return 0;
9048}
9049
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009050sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009051{
9052 my $LibVersion = $_[0];
9053 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9054 {
9055 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009056 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009057
9058 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9059 detect_recursive_includes($RegHeader, $LibVersion);
9060 }
9061
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9063 {
9064 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009065
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009066 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009067 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9068 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009069 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009070 }
9071 }
9072 }
9073}
9074
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009075sub familiarDirs($$)
9076{
9077 my ($D1, $D2) = @_;
9078 if($D1 eq $D2) {
9079 return 1;
9080 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009081
9082 my $U1 = index($D1, "/usr/");
9083 my $U2 = index($D2, "/usr/");
9084
9085 if($U1==0 and $U2!=0) {
9086 return 0;
9087 }
9088
9089 if($U2==0 and $U1!=0) {
9090 return 0;
9091 }
9092
9093 if(index($D2, $D1."/")==0) {
9094 return 1;
9095 }
9096
9097 # /usr/include/DIR
9098 # /home/user/DIR
9099
9100 my $DL = get_depth($D1);
9101
9102 my @Dirs1 = ($D1);
9103 while($DL - get_depth($D1)<=2
9104 and get_depth($D1)>=4
9105 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9106 push(@Dirs1, $D1);
9107 }
9108
9109 my @Dirs2 = ($D2);
9110 while(get_depth($D2)>=4
9111 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9112 push(@Dirs2, $D2);
9113 }
9114
9115 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009116 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009117 foreach my $P2 (@Dirs2)
9118 {
9119
9120 if($P1 eq $P2) {
9121 return 1;
9122 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009123 }
9124 }
9125 return 0;
9126}
9127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009128sub readHeaders($)
9129{
9130 $Version = $_[0];
9131 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9132 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009133 if($Debug)
9134 { # debug mode
9135 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009136 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009137 }
9138 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139}
9140
9141sub prepareTypes($)
9142{
9143 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009144 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009145 { # support for old ABI dumps
9146 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009147 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009149 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9150 if($TName=~/\A(\w+)::(\w+)/) {
9151 my ($P1, $P2) = ($1, $2);
9152 if($P1 eq $P2) {
9153 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009155 else {
9156 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9157 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009159 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160 }
9161 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009162 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009163 { # support for old ABI dumps
9164 # V < 2.5: array size == "number of elements"
9165 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009166 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009167 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009168 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009169 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009170 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009171 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009172 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009173 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009174 $Size *= $Base{"Size"};
9175 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009176 }
9177 else
9178 { # array[] is a pointer
9179 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009180 }
9181 }
9182 }
9183 }
9184 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009185 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009186 { # support for old ABI dumps
9187 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009188 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009189 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009190 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009191 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009192 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009193 my %Type = get_Type($TypeId, $LibVersion);
9194 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9195 my %Type2 = get_Type($TypeId_2, $V2);
9196 if($Type{"Size"} ne $Type2{"Size"}) {
9197 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009198 }
9199 }
9200 }
9201 }
9202}
9203
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009204sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009205{
9206 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009207
9208 if(not keys(%{$SymbolInfo{$LibVersion}}))
9209 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009210 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009211 {
9212 if($CheckHeadersOnly) {
9213 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9214 }
9215 else {
9216 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9217 }
9218 }
9219 }
9220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009221 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009222 if(not checkDump(1, "2.10")
9223 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009224 { # different formats
9225 $Remangle = 1;
9226 }
9227 if($CheckHeadersOnly)
9228 { # different languages
9229 if($UserLang)
9230 { # --lang=LANG for both versions
9231 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9232 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9233 {
9234 if($UserLang eq "C++")
9235 { # remangle symbols
9236 $Remangle = 1;
9237 }
9238 elsif($UserLang eq "C")
9239 { # remove mangling
9240 $Remangle = -1;
9241 }
9242 }
9243 }
9244 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009245
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009246 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009248 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009249 { # support for old ABI dumps
9250 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9251 {
9252 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9253 {
9254 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9255 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009256 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009257 if(defined $DVal and $DVal ne "")
9258 {
9259 if($TName eq "char") {
9260 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9261 }
9262 elsif($TName eq "bool") {
9263 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9264 }
9265 }
9266 }
9267 }
9268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009269 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009270 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009271 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9272 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009273 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009274 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9275 # + support for old ABI dumps
9276 next;
9277 }
9278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009279 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009280 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009281 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009282 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009283
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009284 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009285 if(not checkDump(1, "2.12")
9286 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009287 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009288 if($ShortName eq "operator>>")
9289 {
9290 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9291 { # corrected mangling of operator>>
9292 $SRemangle = 1;
9293 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009294 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009295 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9296 {
9297 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9298 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9299 { # corrected mangling of const global data
9300 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9301 # and incorrectly mangled by old ACC versions
9302 $SRemangle = 1;
9303 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009304 }
9305 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009306 if(not $CheckHeadersOnly)
9307 { # support for old ABI dumps
9308 if(not checkDump(1, "2.17")
9309 or not checkDump(2, "2.17"))
9310 {
9311 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9312 {
9313 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9314 {
9315 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9316 {
9317 $MnglName = $ShortName;
9318 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9319 }
9320 }
9321 }
9322 }
9323 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009324 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009325 { # support for old ABI dumps: some symbols are not mangled in old dumps
9326 # mangle both sets of symbols (old and new)
9327 # NOTE: remangling all symbols by the same mangler
9328 if($MnglName=~/\A_ZN(V|)K/)
9329 { # mangling may be incorrect on old ABI dumps
9330 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009331 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009332 }
9333 if($MnglName=~/\A_ZN(K|)V/)
9334 { # mangling may be incorrect on old ABI dumps
9335 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009336 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009337 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009338 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9339 or (not $ClassID and $CheckHeadersOnly)
9340 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9341 { # support for old ABI dumps, GCC >= 4.0
9342 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009343 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009344 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009345 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 $MangledNames{$LibVersion}{$MnglName} = 1;
9347 }
9348 }
9349 }
9350 elsif($Remangle==-1)
9351 { # remove mangling
9352 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009353 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009355 if(not $MnglName) {
9356 next;
9357 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009358
9359 # NOTE: duplicated entries in the ABI Dump
9360 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9361 {
9362 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9363 {
9364 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9365 {
9366 next;
9367 }
9368 }
9369 }
9370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009371 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9372 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009373 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009376 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009377 { # support for old dumps
9378 # add "Volatile" attribute
9379 if($MnglName=~/_Z(K|)V/) {
9380 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9381 }
9382 }
9383 # symbol and its symlink have same signatures
9384 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009385 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009387
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009388 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9389 {
9390 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009391
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009392 if($SymVer{$LibVersion}{$Alias}) {
9393 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9394 }
9395 }
9396
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009397 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009398 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 }
9400 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9401 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9402 }
9403 if($ExtendedCheck)
9404 { # --ext option
9405 addExtension($LibVersion);
9406 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009407
9408 # clean memory
9409 delete($SymbolInfo{$LibVersion});
9410
9411 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 { # detect allocable classes with public exported constructors
9413 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009414 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009415 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009417 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009418 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9419 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009421 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009422 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009423 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009424 $AllocableClass{$LibVersion}{$ClassName} = 1;
9425 }
9426 }
9427 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009428 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009430 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009431 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009432 if($CheckHeadersOnly)
9433 {
9434 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9435 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9436 { # all symbols except non-virtual inline
9437 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9438 }
9439 }
9440 else {
9441 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009442 }
9443 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009444 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009445 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446 }
9447 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009448 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009449 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009450 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009452 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009453 if(defined $Base{"Type"}
9454 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009455 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009456 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 if($Name=~/<([^<>\s]+)>/)
9458 {
9459 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9460 $ReturnedClass{$LibVersion}{$Tid} = 1;
9461 }
9462 }
9463 else {
9464 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9465 }
9466 }
9467 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009468 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009469 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009470 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009471 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009473 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009474 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009475 if($Base{"Type"}=~/Struct|Class/)
9476 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009477 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009478 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9479 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009480 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009482 }
9483 }
9484 }
9485 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009486
9487 # mapping {short name => symbols}
9488 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009489 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009490 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009491 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009492 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009493 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009494 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009495 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009496 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9497 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009498 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009499 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009500 }
9501 }
9502 }
9503 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009504
9505 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009506 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009507 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009508 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009510 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9511 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009512 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009513 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009514 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009515 $ClassNames{$LibVersion}{$TName} = 1;
9516 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009517 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009518 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9519 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009520 }
9521 }
9522 }
9523 }
9524 }
9525}
9526
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009527sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009529 my ($Tid, $LibVersion) = @_;
9530 if(not $Tid) {
9531 return $Tid;
9532 }
9533
9534 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9535 {
9536 if($TName_Tid{$LibVersion}{$Name}) {
9537 return $TName_Tid{$LibVersion}{$Name};
9538 }
9539 }
9540
9541 return $Tid;
9542}
9543
9544sub register_SymbolUsage($$$)
9545{
9546 my ($InfoId, $UsedType, $LibVersion) = @_;
9547
9548 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9549 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9550 {
9551 register_TypeUsage($RTid, $UsedType, $LibVersion);
9552 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9553 }
9554 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9555 {
9556 register_TypeUsage($FCid, $UsedType, $LibVersion);
9557 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9558
9559 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9560 { # register "this" pointer
9561 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9562 }
9563 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9564 { # register "this" pointer (const method)
9565 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9566 }
9567 }
9568 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9569 {
9570 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9571 {
9572 register_TypeUsage($PTid, $UsedType, $LibVersion);
9573 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9574 }
9575 }
9576 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9577 {
9578 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9579 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9580 register_TypeUsage($TTid, $UsedType, $LibVersion);
9581 }
9582 }
9583}
9584
9585sub register_TypeUsage($$$)
9586{
9587 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009588 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009589 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009590 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009591 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009592 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009593 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009594 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009595
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009596 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009597 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009598 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009599 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009600 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009601 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9602 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9603 }
9604 }
9605
9606 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9607 {
9608 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009609 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009610 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009611 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9612 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009613 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009614 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9615 {
9616 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9617 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009618 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009619 }
9620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009622 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009623 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009624 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9625 {
9626 register_TypeUsage($MTid, $UsedType, $LibVersion);
9627 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009628 }
9629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009630 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009631 or $TInfo{"Type"} eq "MethodPtr"
9632 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009633 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009634 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009635 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009636 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009637 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009638 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9640 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009641 }
9642 }
9643 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009644 if($TInfo{"Type"} eq "FieldPtr")
9645 {
9646 if(my $RTid = $TInfo{"Return"}) {
9647 register_TypeUsage($RTid, $UsedType, $LibVersion);
9648 }
9649 if(my $CTid = $TInfo{"Class"}) {
9650 register_TypeUsage($CTid, $UsedType, $LibVersion);
9651 }
9652 }
9653 if($TInfo{"Type"} eq "MethodPtr")
9654 {
9655 if(my $CTid = $TInfo{"Class"}) {
9656 register_TypeUsage($CTid, $UsedType, $LibVersion);
9657 }
9658 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009659 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009660 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009661 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009662 $UsedType->{$TypeId} = 1;
9663 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9664 {
9665 register_TypeUsage($BTid, $UsedType, $LibVersion);
9666 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9667 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009668 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009669 else
9670 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9671 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009672 }
9673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009674}
9675
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009676sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009677{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009678 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9679
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009680 if($Level eq "Dump")
9681 {
9682 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9683 { # TODO: check if this symbol is from
9684 # base classes of other target symbols
9685 return 1;
9686 }
9687 }
9688
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009689 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9690 { # stdc++ interfaces
9691 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009692 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009693
9694 my $Target = 0;
9695 if(my $Header = $SInfo->{"Header"}) {
9696 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9697 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009698 if($ExtendedCheck)
9699 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009700 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009701 $Target = 1;
9702 }
9703 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009704 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009705 {
9706 if($Target)
9707 {
9708 if($Level eq "Dump")
9709 { # dumped
9710 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009711 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009712 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009713 return 1;
9714 }
9715 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009716 else {
9717 return 1;
9718 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009719 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009720 elsif($Level eq "Source")
9721 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009722 return 1;
9723 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009724 elsif($Level eq "Binary")
9725 { # checked
9726 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9727 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9728 return 1;
9729 }
9730 }
9731 }
9732 }
9733 else
9734 { # library is available
9735 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9736 { # exported symbols
9737 return 1;
9738 }
9739 if($Level eq "Dump")
9740 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009741 if($BinaryOnly)
9742 {
9743 if($SInfo->{"Data"})
9744 {
9745 if($Target) {
9746 return 1;
9747 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009748 }
9749 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009750 else
9751 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009752 if($Target) {
9753 return 1;
9754 }
9755 }
9756 }
9757 elsif($Level eq "Source")
9758 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009759 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009760 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009761 { # skip LOCAL symbols
9762 if($Target) {
9763 return 1;
9764 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009765 }
9766 }
9767 elsif($Level eq "Binary")
9768 { # checked
9769 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9770 {
9771 if($Target) {
9772 return 1;
9773 }
9774 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009775 }
9776 }
9777 return 0;
9778}
9779
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009780sub cleanDump($)
9781{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782 my $LibVersion = $_[0];
9783 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9784 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009785 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9786 {
9787 delete($SymbolInfo{$LibVersion}{$InfoId});
9788 next;
9789 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009790 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009791 if(not $MnglName)
9792 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009793 delete($SymbolInfo{$LibVersion}{$InfoId});
9794 next;
9795 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009796 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009797 if(not $ShortName)
9798 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009799 delete($SymbolInfo{$LibVersion}{$InfoId});
9800 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009801 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009802 if($MnglName eq $ShortName)
9803 { # remove duplicate data
9804 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009805 }
9806 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9807 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9808 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009809 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9810 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9811 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009812 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009813 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009814 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009815 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009816 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9817 {
9818 delete($TypeInfo{$LibVersion}{$Tid});
9819 next;
9820 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009821 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009822 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009823 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009824 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9825 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9826 }
9827 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009828 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9829 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009831 }
9832}
9833
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009834sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009835{
9836 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009837
9838 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9839 {
9840 if(defined $TypeInfo{$LibVersion}{$Dupl})
9841 {
9842 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9843 { # duplicate
9844 return 0;
9845 }
9846 }
9847 }
9848
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009849 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9850
9851 if(isBuiltIn($THeader)) {
9852 return 0;
9853 }
9854
9855 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9856 return 0;
9857 }
9858
9859 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9860 return 0;
9861 }
9862
9863 if(selfTypedef($Tid, $LibVersion)) {
9864 return 0;
9865 }
9866
9867 if(not isTargetType($Tid, $LibVersion)) {
9868 return 0;
9869 }
9870
9871 return 0;
9872}
9873
9874sub isTargetType($$)
9875{
9876 my ($Tid, $LibVersion) = @_;
9877
9878 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9879 { # derived
9880 return 1;
9881 }
9882
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009883 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009884 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009885 if(not is_target_header($THeader, $LibVersion))
9886 { # from target headers
9887 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009888 }
9889 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009890 else
9891 { # NOTE: if type is defined in source
9892 if($UsedDump{$LibVersion}{"Public"})
9893 {
9894 if(isPrivateABI($Tid, $LibVersion)) {
9895 return 0;
9896 }
9897 else {
9898 return 1;
9899 }
9900 }
9901 else {
9902 return 0;
9903 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009904 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009905
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009906 if($SkipInternalTypes)
9907 {
9908 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9909 {
9910 return 0;
9911 }
9912 }
9913
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009914 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009915}
9916
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009917sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009918{ # remove unused data types from the ABI dump
9919 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009920
9921 my %UsedType = ();
9922
9923 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009924 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009925 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009926 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009927 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009928 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009929 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009930 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009931 next;
9932 }
9933
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009934 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009935 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009936 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009937 {
9938 my %Tree = ();
9939 register_TypeUsage($Tid, \%Tree, $LibVersion);
9940
9941 my $Tmpl = 0;
9942 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9943 {
9944 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9945 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9946 {
9947 $Tmpl = 1;
9948 last;
9949 }
9950 }
9951 if(not $Tmpl)
9952 {
9953 foreach (keys(%Tree)) {
9954 $UsedType{$_} = 1;
9955 }
9956 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009957 }
9958 }
9959 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009960
9961 my %Delete = ();
9962
9963 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009964 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009965 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009966 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009967 next;
9968 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009969
9970 if($Kind eq "Extra")
9971 {
9972 my %Tree = ();
9973 register_TypeUsage($Tid, \%Tree, $LibVersion);
9974
9975 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9976 {
9977 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9978 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9979 {
9980 $Delete{$Tid} = 1;
9981 last;
9982 }
9983 }
9984 }
9985 else
9986 {
9987 # remove type
9988 delete($TypeInfo{$LibVersion}{$Tid});
9989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009990 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009991
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009992 if($Kind eq "Extra")
9993 { # remove duplicates
9994 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9995 {
9996 if($UsedType{$Tid})
9997 { # All & Extended
9998 next;
9999 }
10000
10001 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10002
10003 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10004 delete($TypeInfo{$LibVersion}{$Tid});
10005 }
10006 }
10007 }
10008
10009 foreach my $Tid (keys(%Delete))
10010 {
10011 delete($TypeInfo{$LibVersion}{$Tid});
10012 }
10013}
10014
10015sub check_Completeness($$)
10016{
10017 my ($Info, $LibVersion) = @_;
10018
10019 # data types
10020 if(defined $Info->{"Memb"})
10021 {
10022 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10023 {
10024 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10025 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10026 }
10027 }
10028 }
10029 if(defined $Info->{"Base"})
10030 {
10031 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10032 check_TypeInfo($Bid, $LibVersion);
10033 }
10034 }
10035 if(defined $Info->{"BaseType"}) {
10036 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10037 }
10038 if(defined $Info->{"TParam"})
10039 {
10040 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10041 {
10042 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10043 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10044 next;
10045 }
10046 if($TName eq "_BoolType") {
10047 next;
10048 }
10049 if($TName=~/\Asizeof\(/) {
10050 next;
10051 }
10052 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10053 check_TypeInfo($Tid, $LibVersion);
10054 }
10055 else
10056 {
10057 if(defined $Debug) {
10058 printMsg("WARNING", "missed type $TName");
10059 }
10060 }
10061 }
10062 }
10063
10064 # symbols
10065 if(defined $Info->{"Param"})
10066 {
10067 foreach my $Pos (keys(%{$Info->{"Param"}}))
10068 {
10069 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10070 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10071 }
10072 }
10073 }
10074 if(defined $Info->{"Return"}) {
10075 check_TypeInfo($Info->{"Return"}, $LibVersion);
10076 }
10077 if(defined $Info->{"Class"}) {
10078 check_TypeInfo($Info->{"Class"}, $LibVersion);
10079 }
10080}
10081
10082sub check_TypeInfo($$)
10083{
10084 my ($Tid, $LibVersion) = @_;
10085
10086 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10087 return;
10088 }
10089 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10090
10091 if(defined $TypeInfo{$LibVersion}{$Tid})
10092 {
10093 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10094 printMsg("ERROR", "missed type name ($Tid)");
10095 }
10096 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10097 }
10098 else {
10099 printMsg("ERROR", "missed type id $Tid");
10100 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010101}
10102
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010103sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010104{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010105 my ($TypeId, $LibVersion) = @_;
10106 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010107 if($Type{"Type"} eq "Typedef")
10108 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010109 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010110 if($Base{"Type"}=~/Class|Struct/)
10111 {
10112 if($Type{"Name"} eq $Base{"Name"}) {
10113 return 1;
10114 }
10115 elsif($Type{"Name"}=~/::(\w+)\Z/)
10116 {
10117 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10118 { # QPointer<QWidget>::QPointer
10119 return 1;
10120 }
10121 }
10122 }
10123 }
10124 return 0;
10125}
10126
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010127sub addExtension($)
10128{
10129 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010130 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010131 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010132 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010133 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010134 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10135 $TName=~s/\A(struct|union|class|enum) //;
10136 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010137
10138 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10139 "Header" => "extended.h",
10140 "ShortName" => $Symbol,
10141 "MnglName" => $Symbol,
10142 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10143 );
10144
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010145 $ExtendedSymbols{$Symbol} = 1;
10146 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10147 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148 }
10149 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010150 $ExtendedSymbols{"external_func_0"} = 1;
10151 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10152 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010153}
10154
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155sub findMethod($$$)
10156{
10157 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010158 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 {
10160 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10161 return $VirtMethodInClass;
10162 }
10163 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10164 return $VirtMethodInBaseClasses;
10165 }
10166 }
10167 return "";
10168}
10169
10170sub findMethod_Class($$$)
10171{
10172 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010173 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010174 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10175 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10176 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10177 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10178 { # search for interface with the same parameters suffix (overridden)
10179 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10180 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010181 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10182 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010183 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10184 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010185 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10186 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10187 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10188 return $Candidate;
10189 }
10190 }
10191 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010192 else
10193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010194 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10195 return $Candidate;
10196 }
10197 }
10198 }
10199 }
10200 return "";
10201}
10202
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010203sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010204{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010205 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010206 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010208 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10209 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010210 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010211 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010212 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010213 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10214 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 { # pure virtual D2-destructors are marked as "virt" in the dump
10216 # virtual D2-destructors are NOT marked as "virt" in the dump
10217 # both destructors are not presented in the v-table
10218 next;
10219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010220 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010221 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010223 }
10224}
10225
10226sub registerOverriding($)
10227{
10228 my $LibVersion = $_[0];
10229 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010230 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010231 foreach my $ClassName (@Classes)
10232 {
10233 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10234 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010235 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10236 { # pure virtuals
10237 next;
10238 }
10239 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10240 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010241 {
10242 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10243 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10244 { # both overridden virtual methods
10245 # and implemented pure virtual methods
10246 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10247 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10248 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010250 }
10251 }
10252 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10253 delete($VirtualTable{$LibVersion}{$ClassName});
10254 }
10255 }
10256}
10257
10258sub setVirtFuncPositions($)
10259{
10260 my $LibVersion = $_[0];
10261 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10262 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010263 my ($Num, $Rel) = (1, 0);
10264
10265 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010266 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010267 if($UsedDump{$LibVersion}{"DWARF"}) {
10268 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10269 }
10270 else {
10271 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10272 }
10273 foreach my $VirtFunc (@Funcs)
10274 {
10275 if($UsedDump{$LibVersion}{"DWARF"}) {
10276 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10277 }
10278 else {
10279 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10280 }
10281
10282 # set relative positions
10283 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10284 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10285 { # relative position excluding added and removed virtual functions
10286 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10287 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10288 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010292 }
10293 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010294 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010295 {
10296 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010297 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010298 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010299 }
10300 }
10301}
10302
10303sub get_sub_classes($$$)
10304{
10305 my ($ClassId, $LibVersion, $Recursive) = @_;
10306 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10307 my @Subs = ();
10308 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10309 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010310 if($Recursive)
10311 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10313 push(@Subs, $SubSubId);
10314 }
10315 }
10316 push(@Subs, $SubId);
10317 }
10318 return @Subs;
10319}
10320
10321sub get_base_classes($$$)
10322{
10323 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010324 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010325 return () if(not defined $ClassType{"Base"});
10326 my @Bases = ();
10327 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10328 keys(%{$ClassType{"Base"}}))
10329 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010330 if($Recursive)
10331 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010332 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10333 push(@Bases, $SubBaseId);
10334 }
10335 }
10336 push(@Bases, $BaseId);
10337 }
10338 return @Bases;
10339}
10340
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010341sub getVTable_Model($$)
10342{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343 my ($ClassId, $LibVersion) = @_;
10344 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10345 my @Elements = ();
10346 foreach my $BaseId (@Bases, $ClassId)
10347 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010348 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010349 {
10350 if(defined $VirtualTable{$LibVersion}{$BName})
10351 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010352 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10353 if($UsedDump{$LibVersion}{"DWARF"}) {
10354 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10355 }
10356 else {
10357 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10358 }
10359 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010360 push(@Elements, $VFunc);
10361 }
10362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010363 }
10364 }
10365 return @Elements;
10366}
10367
10368sub getVShift($$)
10369{
10370 my ($ClassId, $LibVersion) = @_;
10371 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10372 my $VShift = 0;
10373 foreach my $BaseId (@Bases)
10374 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010375 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010376 {
10377 if(defined $VirtualTable{$LibVersion}{$BName}) {
10378 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010380 }
10381 }
10382 return $VShift;
10383}
10384
10385sub getShift($$)
10386{
10387 my ($ClassId, $LibVersion) = @_;
10388 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10389 my $Shift = 0;
10390 foreach my $BaseId (@Bases)
10391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010392 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010393 {
10394 if($Size!=1)
10395 { # not empty base class
10396 $Shift+=$Size;
10397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010398 }
10399 }
10400 return $Shift;
10401}
10402
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010403sub getVTable_Size($$)
10404{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010405 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010406 my $Size = 0;
10407 # three approaches
10408 if(not $Size)
10409 { # real size
10410 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10411 $Size = keys(%VTable);
10412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010413 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414 if(not $Size)
10415 { # shared library symbol size
10416 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10417 $Size /= $WORD_SIZE{$LibVersion};
10418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010419 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420 if(not $Size)
10421 { # model size
10422 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10423 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10424 }
10425 }
10426 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010427}
10428
10429sub isCopyingClass($$)
10430{
10431 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010432 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010433}
10434
10435sub isLeafClass($$)
10436{
10437 my ($ClassId, $LibVersion) = @_;
10438 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10439}
10440
10441sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010442{ # check structured type for public fields
10443 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010444}
10445
10446sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010447{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448 my ($TypePtr, $Skip, $Start, $End) = @_;
10449 return 0 if(not $TypePtr);
10450 if($End==-1) {
10451 $End = keys(%{$TypePtr->{"Memb"}})-1;
10452 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010453 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010454 {
10455 if($Skip and $Skip->{$MemPos})
10456 { # skip removed/added fields
10457 next;
10458 }
10459 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10460 {
10461 if(isPublic($TypePtr, $MemPos)) {
10462 return ($MemPos+1);
10463 }
10464 }
10465 }
10466 return 0;
10467}
10468
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469sub isReserved($)
10470{ # reserved fields == private
10471 my $MName = $_[0];
10472 if($MName=~/reserved|padding|f_spare/i) {
10473 return 1;
10474 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010475 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010476 return 1;
10477 }
10478 if($MName=~/(pad\d+)/i) {
10479 return 1;
10480 }
10481 return 0;
10482}
10483
10484sub isPublic($$)
10485{
10486 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488 return 0 if(not $TypePtr);
10489 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10490 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010491
10492 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10493 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010494 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010495 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010497
10498 # by name in C language
10499 # TODO: add other methods to detect private members
10500 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010501 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010502 { # C-styled private data
10503 return 0;
10504 }
10505 if(lc($MName) eq "abi")
10506 { # ABI information/reserved field
10507 return 0;
10508 }
10509 if(isReserved($MName))
10510 { # reserved fields
10511 return 0;
10512 }
10513
10514 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515}
10516
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010517sub getVTable_Real($$)
10518{
10519 my ($ClassName, $LibVersion) = @_;
10520 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10521 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010522 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 if(defined $Type{"VTable"}) {
10524 return %{$Type{"VTable"}};
10525 }
10526 }
10527 return ();
10528}
10529
10530sub cmpVTables($)
10531{
10532 my $ClassName = $_[0];
10533 my $Res = cmpVTables_Real($ClassName, 1);
10534 if($Res==-1) {
10535 $Res = cmpVTables_Model($ClassName);
10536 }
10537 return $Res;
10538}
10539
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010540sub cmpVTables_Model($)
10541{
10542 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010543 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010544 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010545 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010546 return 1;
10547 }
10548 }
10549 return 0;
10550}
10551
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553{
10554 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10556 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010557 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010558 my %VTable_Old = getVTable_Real($ClassName, 1);
10559 my %VTable_New = getVTable_Real($ClassName, 2);
10560 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010562 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010563 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10566 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010567 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010568 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010571 my $Entry1 = $VTable_Old{$Offset};
10572 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010574 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010577
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578 $Entry1 = simpleVEntry($Entry1);
10579 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010580
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010581 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010582 { # NOTE: problem with vtable-dumper
10583 next;
10584 }
10585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 if($Entry1 ne $Entry2)
10587 { # register as changed
10588 if($Entry1=~/::([^:]+)\Z/)
10589 {
10590 my $M1 = $1;
10591 if($Entry2=~/::([^:]+)\Z/)
10592 {
10593 my $M2 = $1;
10594 if($M1 eq $M2)
10595 { # overridden
10596 next;
10597 }
10598 }
10599 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010600 if(differentDumps("G"))
10601 {
10602 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10603 {
10604 # GCC 4.6.1: -0x00000000000000010
10605 # GCC 4.7.0: -16
10606 next;
10607 }
10608 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010610 }
10611 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010612 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010613}
10614
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010615sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010616{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010617 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10619 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010620 my $ClassId = $TName_Tid{1}{$ClassName};
10621 if(isPrivateABI($ClassId, 1)) {
10622 next;
10623 }
10624
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010625 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010626 { # already registered
10627 next;
10628 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010630 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010631 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010632 foreach my $Symbol (@Affected)
10633 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010634 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010636 "Target"=>$ClassName);
10637 }
10638 }
10639 }
10640}
10641
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010642sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010643{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010644 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010645 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010647 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010648 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010649
10650 if(isPrivateABI($ClassId, 1)) {
10651 next;
10652 }
10653
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010654 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010655 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010656 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010657 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010658 if($TName_Tid{1}{$ClassName}
10659 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010660 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010661 if(defined $CompleteSignature{1}{$Symbol}
10662 and $CompleteSignature{1}{$Symbol}{"Virt"})
10663 { # override some method in v.1
10664 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010665 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010666 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010667 }
10668 }
10669 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010670 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010672 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010673 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010674 if($TName_Tid{2}{$ClassName}
10675 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010676 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 if(defined $CompleteSignature{2}{$Symbol}
10678 and $CompleteSignature{2}{$Symbol}{"Virt"})
10679 { # override some method in v.2
10680 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010681 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010682 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010683 }
10684 }
10685 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010686 if($Level eq "Binary")
10687 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010688 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010689 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10690 { # check replacements, including pure virtual methods
10691 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10692 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010693 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010694 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10695 if($AddedPos==$RemovedPos)
10696 {
10697 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10698 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10699 last; # other methods will be reported as "added" or "removed"
10700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010701 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010702 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10703 {
10704 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10705 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010706 next;
10707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010708 my $ProblemType = "Virtual_Replacement";
10709 my @Affected = ($RemovedVFunc);
10710 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10711 { # pure methods
10712 if(not isUsedClass($ClassId, 1, $Level))
10713 { # not a parameter of some exported method
10714 next;
10715 }
10716 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010717
10718 # affected all methods (both virtual and non-virtual ones)
10719 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10720 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010721 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010722 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010723 foreach my $AffectedInt (@Affected)
10724 {
10725 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10726 { # affected exported methods only
10727 next;
10728 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010729 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10730 next;
10731 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010732 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10733 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010734 "Target"=>get_Signature($AddedVFunc, 2),
10735 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010737 }
10738 }
10739 }
10740 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010741 if(not checkDump(1, "2.0")
10742 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010743 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010744 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010745 return;
10746 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010747 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010749 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010750 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010751
10752 if(isPrivateABI($ClassId_Old, 1)) {
10753 next;
10754 }
10755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010756 if(not isCreatable($ClassId_Old, 1))
10757 { # skip classes without public constructors (including auto-generated)
10758 # example: class has only a private exported or private inline constructor
10759 next;
10760 }
10761 if($ClassName=~/>/)
10762 { # skip affected template instances
10763 next;
10764 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010765 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010766 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010767 if(not $ClassId_New) {
10768 next;
10769 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010770 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010771 if($Class_New{"Type"}!~/Class|Struct/)
10772 { # became typedef
10773 if($Level eq "Binary") {
10774 next;
10775 }
10776 if($Level eq "Source")
10777 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010778 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010779 if($Class_New{"Type"}!~/Class|Struct/) {
10780 next;
10781 }
10782 $ClassId_New = $Class_New{"Tid"};
10783 }
10784 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010785
10786 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10787 { # incomplete info in the ABI dump
10788 next;
10789 }
10790
10791
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010792 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10793 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 +040010794
10795 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10796 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010799 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10800 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010801 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10802 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 my $Shift_Old = getShift($ClassId_Old, 1);
10804 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010805 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010806 my ($Added, $Removed) = (0, 0);
10807 my @StableBases_Old = ();
10808 foreach my $BaseId (@Bases_Old)
10809 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010810 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010811 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010812 push(@StableBases_Old, $BaseId);
10813 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010814 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010815 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010816 { # removed base
10817 # excluding namespace::SomeClass to SomeClass renaming
10818 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010819 if($Level eq "Binary")
10820 { # Binary-level
10821 if($Shift_Old ne $Shift_New)
10822 { # affected fields
10823 if(havePubFields(\%Class_Old)) {
10824 $ProblemKind .= "_And_Shift";
10825 }
10826 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10827 $ProblemKind .= "_And_Size";
10828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010830 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10831 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010832 { # affected v-table
10833 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010834 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010835 }
10836 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010837 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010838 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10839 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010840 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10841 {
10842 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10843 if($ProblemKind=~/VTable/) {
10844 $VTableChanged_M{$SubName}=1;
10845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010846 }
10847 }
10848 foreach my $Interface (@Affected)
10849 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010850 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10851 next;
10852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010854 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010855 "Target"=>$BaseName,
10856 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10857 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10858 "Shift"=>abs($Shift_New-$Shift_Old) );
10859 }
10860 $Removed+=1;
10861 }
10862 }
10863 my @StableBases_New = ();
10864 foreach my $BaseId (@Bases_New)
10865 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010866 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010867 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 push(@StableBases_New, $BaseId);
10869 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010870 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010871 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010872 { # added base
10873 # excluding namespace::SomeClass to SomeClass renaming
10874 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 if($Level eq "Binary")
10876 { # Binary-level
10877 if($Shift_Old ne $Shift_New)
10878 { # affected fields
10879 if(havePubFields(\%Class_Old)) {
10880 $ProblemKind .= "_And_Shift";
10881 }
10882 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10883 $ProblemKind .= "_And_Size";
10884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010885 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010886 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10887 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010888 { # affected v-table
10889 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010890 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010891 }
10892 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010893 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010894 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10895 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010896 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10897 {
10898 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10899 if($ProblemKind=~/VTable/) {
10900 $VTableChanged_M{$SubName}=1;
10901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010902 }
10903 }
10904 foreach my $Interface (@Affected)
10905 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010906 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10907 next;
10908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010910 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010911 "Target"=>$BaseName,
10912 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10913 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10914 "Shift"=>abs($Shift_New-$Shift_Old) );
10915 }
10916 $Added+=1;
10917 }
10918 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010919 if($Level eq "Binary")
10920 { # Binary-level
10921 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010922 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10923 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010926 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010927 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010928 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010929 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10930 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010931 if($NewPos!=$OldPos)
10932 { # changed position of the base class
10933 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010934 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010935 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10936 next;
10937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010938 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10939 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 "Target"=>$BaseName,
10941 "Old_Value"=>$OldPos-1,
10942 "New_Value"=>$NewPos-1 );
10943 }
10944 }
10945 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10946 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10947 { # became non-virtual base
10948 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10949 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010950 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10951 next;
10952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10954 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010955 "Target"=>$BaseName );
10956 }
10957 }
10958 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10959 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10960 { # became virtual base
10961 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10962 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010963 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10964 next;
10965 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10967 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010968 "Target"=>$BaseName );
10969 }
10970 }
10971 }
10972 }
10973 # detect size changes in base classes
10974 if($Shift_Old!=$Shift_New)
10975 { # size of allocable class
10976 foreach my $BaseId (@StableBases_Old)
10977 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010978 my %BaseType = get_Type($BaseId, 1);
10979 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010980 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010981 if($Size_Old ne $Size_New
10982 and $Size_Old and $Size_New)
10983 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010984 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010985 if(isCopyingClass($BaseId, 1)) {
10986 $ProblemType = "Size_Of_Copying_Class";
10987 }
10988 elsif($AllocableClass{1}{$BaseType{"Name"}})
10989 {
10990 if($Size_New>$Size_Old)
10991 { # increased size
10992 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010993 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010994 else
10995 { # decreased size
10996 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10997 if(not havePubFields(\%Class_Old))
10998 { # affected class has no public members
10999 next;
11000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 }
11003 next if(not $ProblemType);
11004 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11005 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011006 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11007 next;
11008 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011009 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11010 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011011 "Target"=>$BaseType{"Name"},
11012 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11013 "New_Size"=>$Size_New*$BYTE_SIZE );
11014 }
11015 }
11016 }
11017 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011018 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011019 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011020 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011021 { # compare virtual tables size in base classes
11022 my $VShift_Old = getVShift($ClassId_Old, 1);
11023 my $VShift_New = getVShift($ClassId_New, 2);
11024 if($VShift_Old ne $VShift_New)
11025 { # changes in the base class or changes in the list of base classes
11026 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11027 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11028 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011029 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 foreach my $BaseId (@AllBases_Old)
11031 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011032 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011033 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011034 { # lost base
11035 next;
11036 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011037 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11038 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011039 if($VSize_Old!=$VSize_New)
11040 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011041 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011042 { # TODO: affected non-virtual methods?
11043 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011044 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11045 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011046 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011047 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011048 { # skip interfaces that have not changed the absolute virtual position
11049 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011050 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011051 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11052 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011053 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011054 $VTableChanged_M{$BaseType{"Name"}} = 1;
11055 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11057 { # the reason of the layout change: added virtual functions
11058 next if($VirtualReplacement{$VirtFunc});
11059 my $ProblemType = "Added_Virtual_Method";
11060 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11061 $ProblemType = "Added_Pure_Virtual_Method";
11062 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011063 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011064 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 "Target"=>get_Signature($VirtFunc, 2) );
11066 }
11067 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11068 { # the reason of the layout change: removed virtual functions
11069 next if($VirtualReplacement{$VirtFunc});
11070 my $ProblemType = "Removed_Virtual_Method";
11071 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11072 $ProblemType = "Removed_Pure_Virtual_Method";
11073 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011074 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011075 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011076 "Target"=>get_Signature($VirtFunc, 1) );
11077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 }
11079 }
11080 }
11081 }
11082 }
11083 }
11084 }
11085}
11086
11087sub isCreatable($$)
11088{
11089 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011090 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011091 or isCopyingClass($ClassId, $LibVersion)) {
11092 return 1;
11093 }
11094 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11095 { # Fix for incomplete data: if this class has
11096 # a base class then it should also has a constructor
11097 return 1;
11098 }
11099 if($ReturnedClass{$LibVersion}{$ClassId})
11100 { # returned by some method of this class
11101 # or any other class
11102 return 1;
11103 }
11104 return 0;
11105}
11106
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011107sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011108{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011109 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011110 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11111 { # parameter of some exported method
11112 return 1;
11113 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011114 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11115 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011116 { # method from target class
11117 return 1;
11118 }
11119 return 0;
11120}
11121
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011122sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011123{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011125 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011126 # - virtual
11127 # - pure-virtual
11128 # - non-virtual
11129 if($CompleteSignature{1}{$Interface}{"Data"})
11130 { # global data is not affected
11131 return;
11132 }
11133 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011134 if(not $Class_Id) {
11135 return;
11136 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011137 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011138 if(cmpVTables_Real($CName, 1)==0)
11139 { # no changes
11140 return;
11141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011142 $CheckedTypes{$Level}{$CName} = 1;
11143 if($Level eq "Binary")
11144 { # Binary-level
11145 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11146 and not isUsedClass($Class_Id, 1, $Level))
11147 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011148 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011149 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011150 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011151 }
11152 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11153 {
11154 if(defined $VirtualTable{2}{$CName}{$Func}
11155 and defined $CompleteSignature{2}{$Func})
11156 {
11157 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11158 and $CompleteSignature{2}{$Func}{"PureVirt"})
11159 { # became pure virtual
11160 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11161 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011162 "Target"=>get_Signature_M($Func, 1) );
11163 $VTableChanged_M{$CName} = 1;
11164 }
11165 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11166 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11167 { # became non-pure virtual
11168 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11169 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011170 "Target"=>get_Signature_M($Func, 1) );
11171 $VTableChanged_M{$CName} = 1;
11172 }
11173 }
11174 }
11175 if($Level eq "Binary")
11176 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011177 # check virtual table structure
11178 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11179 {
11180 next if($Interface eq $AddedVFunc);
11181 next if($VirtualReplacement{$AddedVFunc});
11182 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11183 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11184 { # pure virtual methods affect all others (virtual and non-virtual)
11185 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011186 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011187 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011188 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011189 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011190 elsif(not defined $VirtualTable{1}{$CName}
11191 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011192 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011193 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 { # became polymorphous class, added v-table pointer
11195 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011196 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011197 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011198 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011199 }
11200 else
11201 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011202 my $VSize_Old = getVTable_Size($CName, 1);
11203 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011204 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 if(isCopyingClass($Class_Id, 1))
11206 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11207 my $ProblemType = "Added_Virtual_Method";
11208 if(isLeafClass($Class_Id, 1)) {
11209 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11210 }
11211 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11212 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011214 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 else
11217 {
11218 my $ProblemType = "Added_Virtual_Method";
11219 if(isLeafClass($Class_Id, 1)) {
11220 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11221 }
11222 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11223 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011224 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011225 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011227 }
11228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011229 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11230 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011231 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011232 if(defined $VirtualTable{1}{$CName}
11233 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011234 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011235 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11236 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011237
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011238 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011239 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011240 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11241 foreach my $ASymbol (@Affected)
11242 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011243 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11244 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011245 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011246 next;
11247 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011248 }
11249 $CheckedSymbols{$Level}{$ASymbol} = 1;
11250 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11251 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011252 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011253 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011256 }
11257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011258 else {
11259 # safe
11260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011262 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11263 {
11264 next if($VirtualReplacement{$RemovedVFunc});
11265 if($RemovedVFunc eq $Interface
11266 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11267 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011268 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011269 next;
11270 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011271 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011272 { # became non-polymorphous class, removed v-table pointer
11273 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11274 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011276 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011277 }
11278 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11279 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11280 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011281 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011282 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011283 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11284 next;
11285 }
11286 my $VPos_New = -1;
11287 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011288 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011289 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11290 }
11291 else
11292 {
11293 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011294 next;
11295 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011296 }
11297 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11298 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11299 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11300 {
11301 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11302 foreach my $ASymbol (@Affected)
11303 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011304 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11305 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011306 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011307 next;
11308 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011309 }
11310 my $ProblemType = "Removed_Virtual_Method";
11311 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11312 $ProblemType = "Removed_Pure_Virtual_Method";
11313 }
11314 $CheckedSymbols{$Level}{$ASymbol} = 1;
11315 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11316 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011317 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011318 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011320 }
11321 }
11322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011323 }
11324 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011325 else
11326 { # Source-level
11327 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011328 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011329 next if($Interface eq $AddedVFunc);
11330 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011331 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011332 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11333 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011334 "Target"=>get_Signature($AddedVFunc, 2) );
11335 }
11336 }
11337 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11338 {
11339 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11340 {
11341 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11342 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011343 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 }
11345 }
11346 }
11347}
11348
11349sub find_MemberPair_Pos_byName($$)
11350{
11351 my ($Member_Name, $Pair_Type) = @_;
11352 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11353 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11354 {
11355 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11356 {
11357 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11358 $Name=~s/\A[_]+|[_]+\Z//g;
11359 if($Name eq $Member_Name) {
11360 return $MemberPair_Pos;
11361 }
11362 }
11363 }
11364 return "lost";
11365}
11366
11367sub find_MemberPair_Pos_byVal($$)
11368{
11369 my ($Member_Value, $Pair_Type) = @_;
11370 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11371 {
11372 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11373 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11374 return $MemberPair_Pos;
11375 }
11376 }
11377 return "lost";
11378}
11379
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011380sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011381{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011382 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011384 if( $_->{"T1"} eq $_[0]
11385 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011386 {
11387 return 1;
11388 }
11389 }
11390 return 0;
11391}
11392
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011393sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011394{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011395 my %IDs = (
11396 "T1" => $_[0],
11397 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011398 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011399 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011400}
11401
11402sub isRenamed($$$$$)
11403{
11404 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11405 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11406 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011407 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011408 if(not defined $Type2->{"Memb"}{$MemPos}) {
11409 return "";
11410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011411 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011412 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011413
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011414 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11415 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011416 if($MemberPair_Pos_Rev eq "lost")
11417 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011418 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11419 { # base type match
11420 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011421 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011422 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11423 { # exact type match
11424 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011425 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011426 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11427 { # size match
11428 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011430 if(isReserved($Pair_Name))
11431 { # reserved fields
11432 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011433 }
11434 }
11435 return "";
11436}
11437
11438sub isLastElem($$)
11439{
11440 my ($Pos, $TypeRef) = @_;
11441 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011442 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011443 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11444 return 1;
11445 }
11446 elsif($Name=~/END|NLIMITS\Z/)
11447 { # __RLIMIT_NLIMITS
11448 return 1;
11449 }
11450 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11451 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11452 { # NImageFormats, NColorRoles
11453 return 1;
11454 }
11455 return 0;
11456}
11457
11458sub nonComparable($$)
11459{
11460 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011461
11462 my $N1 = $T1->{"Name"};
11463 my $N2 = $T2->{"Name"};
11464
11465 $N1=~s/\A(struct|union|enum) //;
11466 $N2=~s/\A(struct|union|enum) //;
11467
11468 if($N1 ne $N2
11469 and not isAnon($N1)
11470 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011471 { # different names
11472 if($T1->{"Type"} ne "Pointer"
11473 or $T2->{"Type"} ne "Pointer")
11474 { # compare base types
11475 return 1;
11476 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011477 if($N1!~/\Avoid\s*\*/
11478 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011479 {
11480 return 1;
11481 }
11482 }
11483 elsif($T1->{"Type"} ne $T2->{"Type"})
11484 { # different types
11485 if($T1->{"Type"} eq "Class"
11486 and $T2->{"Type"} eq "Struct")
11487 { # "class" to "struct"
11488 return 0;
11489 }
11490 elsif($T2->{"Type"} eq "Class"
11491 and $T1->{"Type"} eq "Struct")
11492 { # "struct" to "class"
11493 return 0;
11494 }
11495 else
11496 { # "class" to "enum"
11497 # "union" to "class"
11498 # ...
11499 return 1;
11500 }
11501 }
11502 return 0;
11503}
11504
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011505sub isOpaque($)
11506{
11507 my $T = $_[0];
11508 if(not defined $T->{"Memb"})
11509 {
11510 return 1;
11511 }
11512 return 0;
11513}
11514
11515sub removeVPtr($)
11516{ # support for old ABI dumps
11517 my $TPtr = $_[0];
11518 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11519 if($#Pos>=1)
11520 {
11521 foreach my $Pos (0 .. $#Pos-1)
11522 {
11523 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11524 }
11525 delete($TPtr->{"Memb"}{$#Pos});
11526 }
11527}
11528
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011529sub isPrivateABI($$)
11530{
11531 my ($TypeId, $LibVersion) = @_;
11532
11533 if($CheckPrivateABI) {
11534 return 0;
11535 }
11536
11537 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11538 return 1;
11539 }
11540
11541 return 0;
11542}
11543
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011544sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011545{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011546 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011547 return {} if(not $Type1_Id or not $Type2_Id);
11548
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011549 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011550 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011551 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011552 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011553
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011554 my %Type1 = get_Type($Type1_Id, 1);
11555 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011556 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011557 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011558 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011559
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011560 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11561 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011562
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011563 if(defined $UsedDump{1}{"DWARF"})
11564 {
11565 if($Type1_Pure{"Name"} eq "__unknown__"
11566 or $Type2_Pure{"Name"} eq "__unknown__")
11567 { # Error ABI dump
11568 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11569 }
11570 }
11571
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011572 if(isPrivateABI($Type1_Id, 1)) {
11573 return {};
11574 }
11575
11576 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11577 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11578
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011579 my %SubProblems = ();
11580
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011581 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11582 {
11583 if($Type1_Pure{"Type"}=~/Struct|Union/
11584 and $Type2_Pure{"Type"}=~/Struct|Union/)
11585 {
11586 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11587 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011588 if(not defined $UsedDump{1}{"DWARF"}
11589 and not defined $UsedDump{2}{"DWARF"})
11590 {
11591 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11592 "Target"=>$Type1_Pure{"Name"},
11593 "Type_Name"=>$Type1_Pure{"Name"} );
11594 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011595
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011596 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011597 }
11598 }
11599 }
11600
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011601 if(not $Type1_Pure{"Size"}
11602 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011603 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011604 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11605 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11606 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011607 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011608 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011609 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011610 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011611 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011612 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011613 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011614 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11615 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11616 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011617
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011618 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11619 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011620 }
11621
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011622 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11623 { # support for old ABI dumps
11624 # _vptr field added in 3.0
11625 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11626 {
11627 if(defined $Type2_Pure{"Memb"}
11628 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11629 {
11630 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11631 delete($Type2_Pure{"Memb"}{0});
11632 }
11633 else {
11634 removeVPtr(\%Type2_Pure);
11635 }
11636 }
11637 }
11638 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11639 {
11640 if(defined $Type1_Pure{"Memb"}
11641 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11642 {
11643 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11644 delete($Type1_Pure{"Memb"}{0});
11645 }
11646 else {
11647 removeVPtr(\%Type1_Pure);
11648 }
11649 }
11650 }
11651 }
11652
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011653 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11654 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011655
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011656 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011657 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11658 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011659 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011660 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11661 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011662 if($Base_1{"Name"} ne $Base_2{"Name"})
11663 {
11664 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011665 or differentDumps("V")
11666 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011667 { # different GCC versions or different dumps
11668 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11669 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11670 # std::__va_list and __va_list
11671 $Base_1{"Name"}=~s/\A(\w+::)+//;
11672 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011673 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11674 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011676 }
11677 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11678 and $Base_1{"Name"} ne $Base_2{"Name"})
11679 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011680 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011681 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011682 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011683 {
11684 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11685 "Target"=>$Typedef_1{"Name"},
11686 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011687 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11688 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11689 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011690 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11691 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011692
11693 if(defined $UsedDump{1}{"DWARF"})
11694 {
11695 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11696 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11697 { # Error ABI dump
11698 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11699 }
11700 }
11701
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011702 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011703 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011704 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11705 {
11706 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11707 "Target"=>$Typedef_1{"Name"},
11708 "Type_Name"=>$Typedef_1{"Name"},
11709 "Old_Value"=>$Base_1{"Name"},
11710 "New_Value"=>$Base_2{"Name"} );
11711 }
11712 else
11713 {
11714 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11715 "Target"=>$Typedef_1{"Name"},
11716 "Type_Name"=>$Typedef_1{"Name"},
11717 "Old_Value"=>$Base_1{"Name"},
11718 "New_Value"=>$Base_2{"Name"} );
11719 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011721 }
11722 }
11723 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11724 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011725 my $TT1 = $Type1_Pure{"Type"};
11726 my $TT2 = $Type2_Pure{"Type"};
11727
11728 if($TT1 ne $TT2
11729 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011730 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011731 my $Short1 = $Type1_Pure{"Name"};
11732 my $Short2 = $Type2_Pure{"Name"};
11733
11734 $Short1=~s/\A\Q$TT1\E //ig;
11735 $Short2=~s/\A\Q$TT2\E //ig;
11736
11737 if($Short1 eq $Short2)
11738 {
11739 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11740 "Target"=>$Type1_Pure{"Name"},
11741 "Type_Name"=>$Type1_Pure{"Name"},
11742 "Old_Value"=>lc($Type1_Pure{"Type"}),
11743 "New_Value"=>lc($Type2_Pure{"Type"}) );
11744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011745 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011746 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011747 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011748
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011749 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11752 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11753 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11754 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011755 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011756 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011757 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011758 {
11759 my $ProblemKind = "DataType_Size";
11760 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011761 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 {
11763 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11764 $ProblemKind = "Size_Of_Copying_Class";
11765 }
11766 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11767 {
11768 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11769 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11770 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011771 else
11772 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011773 # descreased size of allocable class
11774 # it has no special effects
11775 }
11776 }
11777 }
11778 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11779 "Target"=>$Type1_Pure{"Name"},
11780 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011781 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011782 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 }
11784 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011785 if(defined $Type1_Pure{"BaseType"}
11786 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011787 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011788 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11789 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011790 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011791 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11792 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011793 }
11794 }
11795 }
11796 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11797 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11798 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11799 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11800 { # detect removed and renamed fields
11801 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11802 next if(not $Member_Name);
11803 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);
11804 if($MemberPair_Pos eq "lost")
11805 {
11806 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11807 {
11808 if(isUnnamed($Member_Name))
11809 { # support for old-version dumps
11810 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011811 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011812 next;
11813 }
11814 }
11815 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11816 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011817 $RenamedField{$Member_Pos} = $RenamedTo;
11818 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011819 }
11820 else
11821 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011822 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 }
11824 }
11825 elsif($Type1_Pure{"Type"} eq "Enum")
11826 {
11827 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11828 next if($Member_Value1 eq "");
11829 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11830 if($MemberPair_Pos ne "lost")
11831 { # renamed
11832 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11833 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11834 if($MemberPair_Pos_Rev eq "lost")
11835 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011836 $RenamedField{$Member_Pos} = $RenamedTo;
11837 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011838 }
11839 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011840 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011841 }
11842 }
11843 else
11844 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011845 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011846 }
11847 }
11848 }
11849 else
11850 { # related
11851 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11852 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11853 }
11854 }
11855 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11856 { # detect added fields
11857 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11858 next if(not $Member_Name);
11859 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);
11860 if($MemberPair_Pos eq "lost")
11861 {
11862 if(isUnnamed($Member_Name))
11863 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011864 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011865 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011866 next;
11867 }
11868 }
11869 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11870 {
11871 if(not $RenamedField_Rev{$Member_Pos})
11872 { # added
11873 $AddedField{$Member_Pos}=1;
11874 }
11875 }
11876 }
11877 }
11878 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11879 { # detect moved fields
11880 my (%RelPos, %RelPosName, %AbsPos) = ();
11881 my $Pos = 0;
11882 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11883 { # relative positions in 1st version
11884 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11885 next if(not $Member_Name);
11886 if(not $RemovedField{$Member_Pos})
11887 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011888 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011889 $RelPosName{1}{$Pos} = $Member_Name;
11890 $AbsPos{1}{$Pos++} = $Member_Pos;
11891 }
11892 }
11893 $Pos = 0;
11894 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11895 { # relative positions in 2nd version
11896 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11897 next if(not $Member_Name);
11898 if(not $AddedField{$Member_Pos})
11899 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011900 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011901 $RelPosName{2}{$Pos} = $Member_Name;
11902 $AbsPos{2}{$Pos++} = $Member_Pos;
11903 }
11904 }
11905 foreach my $Member_Name (keys(%{$RelPos{1}}))
11906 {
11907 my $RPos1 = $RelPos{1}{$Member_Name};
11908 my $AbsPos1 = $NameToPosA{$Member_Name};
11909 my $Member_Name2 = $Member_Name;
11910 if(my $RenamedTo = $RenamedField{$AbsPos1})
11911 { # renamed
11912 $Member_Name2 = $RenamedTo;
11913 }
11914 my $RPos2 = $RelPos{2}{$Member_Name2};
11915 if($RPos2 ne "" and $RPos1 ne $RPos2)
11916 { # different relative positions
11917 my $AbsPos2 = $NameToPosB{$Member_Name2};
11918 if($AbsPos1 ne $AbsPos2)
11919 { # different absolute positions
11920 my $ProblemType = "Moved_Field";
11921 if(not isPublic(\%Type1_Pure, $AbsPos1))
11922 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011923 if($Level eq "Source") {
11924 next;
11925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011926 $ProblemType = "Moved_Private_Field";
11927 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011928 if($Level eq "Binary"
11929 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011930 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011931 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011932 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011933 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011934 if($MemSize1 ne $MemSize2) {
11935 $ProblemType .= "_And_Size";
11936 }
11937 }
11938 if($ProblemType eq "Moved_Private_Field") {
11939 next;
11940 }
11941 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11942 "Target"=>$Member_Name,
11943 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011944 "Old_Value"=>$RPos1,
11945 "New_Value"=>$RPos2 );
11946 }
11947 }
11948 }
11949 }
11950 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011951 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011952 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11953 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011954 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 if(my $RenamedTo = $RenamedField{$Member_Pos})
11956 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011957 if(defined $Constants{2}{$Member_Name})
11958 {
11959 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11960 { # define OLD NEW
11961 next; # Safe
11962 }
11963 }
11964
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11966 {
11967 if(isPublic(\%Type1_Pure, $Member_Pos))
11968 {
11969 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11970 "Target"=>$Member_Name,
11971 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011972 "Old_Value"=>$Member_Name,
11973 "New_Value"=>$RenamedTo );
11974 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011975 elsif(isReserved($Member_Name))
11976 {
11977 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11978 "Target"=>$Member_Name,
11979 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011980 "Old_Value"=>$Member_Name,
11981 "New_Value"=>$RenamedTo );
11982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 }
11984 elsif($Type1_Pure{"Type"} eq "Enum")
11985 {
11986 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11987 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11988 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011989 "Old_Value"=>$Member_Name,
11990 "New_Value"=>$RenamedTo );
11991 }
11992 }
11993 elsif($RemovedField{$Member_Pos})
11994 { # removed
11995 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11996 {
11997 my $ProblemType = "Removed_Field";
11998 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011999 or isUnnamed($Member_Name))
12000 {
12001 if($Level eq "Source") {
12002 next;
12003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 $ProblemType = "Removed_Private_Field";
12005 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012006 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012007 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012008 {
12009 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
12010 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012011 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 +040012012 { # changed offset
12013 $ProblemType .= "_And_Layout";
12014 }
12015 }
12016 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
12017 { # affected size
12018 $ProblemType .= "_And_Size";
12019 }
12020 }
12021 if($ProblemType eq "Removed_Private_Field") {
12022 next;
12023 }
12024 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12025 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012026 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012027 }
12028 elsif($Type2_Pure{"Type"} eq "Union")
12029 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012030 if($Level eq "Binary"
12031 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012032 {
12033 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12034 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012035 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012036 }
12037 else
12038 {
12039 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12040 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012041 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012042 }
12043 }
12044 elsif($Type1_Pure{"Type"} eq "Enum")
12045 {
12046 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12047 "Target"=>$Member_Name,
12048 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012049 "Old_Value"=>$Member_Name );
12050 }
12051 }
12052 else
12053 { # changed
12054 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12055 if($Type1_Pure{"Type"} eq "Enum")
12056 {
12057 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12058 next if($Member_Value1 eq "");
12059 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12060 next if($Member_Value2 eq "");
12061 if($Member_Value1 ne $Member_Value2)
12062 {
12063 my $ProblemType = "Enum_Member_Value";
12064 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12065 $ProblemType = "Enum_Last_Member_Value";
12066 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012067 if($SkipConstants{1}{$Member_Name}) {
12068 $ProblemType = "Enum_Private_Member_Value";
12069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12071 "Target"=>$Member_Name,
12072 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012073 "Old_Value"=>$Member_Value1,
12074 "New_Value"=>$Member_Value2 );
12075 }
12076 }
12077 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12078 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012079 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12080 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12081
12082 if($Access1 ne "private"
12083 and $Access2 eq "private")
12084 {
12085 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12086 "Target"=>$Member_Name,
12087 "Type_Name"=>$Type1_Pure{"Name"});
12088 }
12089 elsif($Access1 ne "protected"
12090 and $Access1 ne "private"
12091 and $Access2 eq "protected")
12092 {
12093 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12094 "Target"=>$Member_Name,
12095 "Type_Name"=>$Type1_Pure{"Name"});
12096 }
12097
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012098 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12099 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012100 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012101 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12102 $SizeV1 = $BSize1;
12103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012104 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012105 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12106 $SizeV2 = $BSize2;
12107 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012108 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12109 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012110 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012111 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012112 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012113 {
12114 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12115 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12116 { # field size change (including anon-structures and unions)
12117 # - same types
12118 # - unnamed types
12119 # - bitfields
12120 my $ProblemType = "Field_Size";
12121 if(not isPublic(\%Type1_Pure, $Member_Pos)
12122 or isUnnamed($Member_Name))
12123 { # should not be accessed by applications, goes to "Low Severity"
12124 # example: "abidata" members in GStreamer types
12125 $ProblemType = "Private_".$ProblemType;
12126 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012127 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 +040012128 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012129 if($Type2_Pure{"Type"} ne "Union"
12130 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012131 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012132 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 +040012133 { # changed offset
12134 $ProblemType .= "_And_Layout";
12135 }
12136 }
12137 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12138 $ProblemType .= "_And_Type_Size";
12139 }
12140 }
12141 if($ProblemType eq "Private_Field_Size")
12142 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012143 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012144 if($ProblemType eq "Field_Size")
12145 {
12146 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12147 { # Low severity
12148 $ProblemType = "Struct_Field_Size_Increased";
12149 }
12150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012151 if($ProblemType)
12152 { # register a problem
12153 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12154 "Target"=>$Member_Name,
12155 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012156 "Old_Size"=>$SizeV1,
12157 "New_Size"=>$SizeV2);
12158 }
12159 }
12160 }
12161 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12162 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12163 { # do NOT check bitfield type changes
12164 next;
12165 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012166 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012167 {
12168 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12169 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12170 {
12171 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12172 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012173 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012174 }
12175 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12176 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12177 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012178 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012179 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012180 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012181 }
12182 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012183 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12184 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012185 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012186 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12187 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012188
12189 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012190 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012191 or $ProblemType eq "Field_Type_And_Size"
12192 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012193 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012194 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012195 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012196 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012197 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012198 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012200 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012201 }
12202 }
12203 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12204 {
12205 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012206 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012207 }
12208 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012209 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012210 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012211 }
12212 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12213 {
12214 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012215 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012216 }
12217 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012218 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012219 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012220 }
12221 }
12222 }
12223
12224 if($Level eq "Source")
12225 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012226 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012227 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012228 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12229 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012230
12231 if($ProblemType eq "Field_Type")
12232 {
12233 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012234 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012235 }
12236 }
12237 }
12238 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012239
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012240 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012241 {
12242 my $ProblemType_Init = $ProblemType;
12243 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012244 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012245 if(not isPublic(\%Type1_Pure, $Member_Pos)
12246 or isUnnamed($Member_Name)) {
12247 $ProblemType = "Private_".$ProblemType;
12248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012249 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 +040012250 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012251 if($Type2_Pure{"Type"} ne "Union"
12252 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012253 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012254 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 +040012255 { # changed offset
12256 $ProblemType .= "_And_Layout";
12257 }
12258 }
12259 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12260 $ProblemType .= "_And_Type_Size";
12261 }
12262 }
12263 }
12264 else
12265 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012266 # TODO: Private_Field_Type rule?
12267
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 if(not isPublic(\%Type1_Pure, $Member_Pos)
12269 or isUnnamed($Member_Name)) {
12270 next;
12271 }
12272 }
12273 if($ProblemType eq "Private_Field_Type_And_Size")
12274 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 }
12276 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12277 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012278 "Type_Name"=>$Type1_Pure{"Name"});
12279
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012280 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012282 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 }
12284 }
12285 if(not isPublic(\%Type1_Pure, $Member_Pos))
12286 { # do NOT check internal type changes
12287 next;
12288 }
12289 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012290 { # checking member type changes
12291 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12292
12293 my %DupProblems = ();
12294
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012295 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012297 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012299 if(not defined $AllAffected)
12300 {
12301 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12302 next;
12303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012305
12306 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12307 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12308
12309 if(not defined $AllAffected)
12310 {
12311 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012312 }
12313 }
12314 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012315
12316 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 }
12318 }
12319 }
12320 }
12321 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12322 { # checking added members, public and private
12323 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12324 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012325 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012326 if($AddedField{$Member_Pos})
12327 { # added
12328 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12329 {
12330 my $ProblemType = "Added_Field";
12331 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012332 or isUnnamed($Member_Name))
12333 {
12334 if($Level eq "Source") {
12335 next;
12336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337 $ProblemType = "Added_Private_Field";
12338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012339 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012340 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012341 {
12342 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12343 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012344 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 +040012345 { # changed offset
12346 $ProblemType .= "_And_Layout";
12347 }
12348 }
12349 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12350 $ProblemType .= "_And_Size";
12351 }
12352 }
12353 if($ProblemType eq "Added_Private_Field")
12354 { # skip added private fields
12355 next;
12356 }
12357 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12358 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012359 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012360 }
12361 elsif($Type2_Pure{"Type"} eq "Union")
12362 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012363 if($Level eq "Binary"
12364 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365 {
12366 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12367 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012368 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012369 }
12370 else
12371 {
12372 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12373 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012374 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375 }
12376 }
12377 elsif($Type2_Pure{"Type"} eq "Enum")
12378 {
12379 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12380 next if($Member_Value eq "");
12381 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12382 "Target"=>$Member_Name,
12383 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012384 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 }
12386 }
12387 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012388
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012389 if($Type1_Pure{"Type"} eq "FuncPtr")
12390 {
12391 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12392 {
12393 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12394 next;
12395 }
12396
12397 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12398 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12399
12400 my $PName = "p".$PPos;
12401
12402 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12403 my %DupProblems = ();
12404
12405 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12406 {
12407 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12408 {
12409 if(not defined $AllAffected)
12410 {
12411 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12412 next;
12413 }
12414 }
12415
12416 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12417 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12418
12419 if(not defined $AllAffected)
12420 {
12421 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12422 }
12423 }
12424 }
12425
12426 %DupProblems = ();
12427 }
12428 }
12429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012430 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012431 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432}
12433
12434sub isUnnamed($) {
12435 return $_[0]=~/\Aunnamed\d+\Z/;
12436}
12437
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012438sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012439{
12440 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012441 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12442 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12443 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012445 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012446 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012447 }
12448 return $TypeName;
12449}
12450
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012451sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012453 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012454 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012455 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12456 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012458 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12459 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460 return () if(not $Type{"Type"});
12461 if($Type{"Type"} ne $Type_Type)
12462 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012463 return () if(not $Type{"BaseType"});
12464 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012465 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012467 return %Type;
12468}
12469
12470my %TypeSpecAttributes = (
12471 "Const" => 1,
12472 "Volatile" => 1,
12473 "ConstVolatile" => 1,
12474 "Restrict" => 1,
12475 "Typedef" => 1
12476);
12477
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012478sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012479{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012480 my ($TypeId, $Info) = @_;
12481 if(not $TypeId or not $Info
12482 or not $Info->{$TypeId}) {
12483 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012484 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012485 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12486 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12487 }
12488 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012489 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012491 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012492 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012493 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012494 return %Type;
12495}
12496
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012497sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012498{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012499 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012501 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12502 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012503 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012504 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12505 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012506 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12507 my $PLevel = 0;
12508 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12509 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012510 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012511 return $PLevel if(not $Type{"BaseType"});
12512 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12513 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12514 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515}
12516
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012517sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012518{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012519 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012520 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012521 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12522 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012524 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12525 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012526 return %Type if(not $Type{"BaseType"});
12527 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012528 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529 return %Type;
12530}
12531
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012532sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012533{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012534 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012535 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012536 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12537 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012538 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012539 my $Qual = "";
12540 if($Type{"Type"} eq "Pointer") {
12541 $Qual .= "*";
12542 }
12543 elsif($Type{"Type"} eq "Ref") {
12544 $Qual .= "&";
12545 }
12546 elsif($Type{"Type"} eq "ConstVolatile") {
12547 $Qual .= "const volatile";
12548 }
12549 elsif($Type{"Type"} eq "Const"
12550 or $Type{"Type"} eq "Volatile"
12551 or $Type{"Type"} eq "Restrict") {
12552 $Qual .= lc($Type{"Type"});
12553 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012554 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555 return $BQual.$Qual;
12556}
12557
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012558sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012559{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012560 my ($TypeId, $Info) = @_;
12561 if(not $TypeId or not $Info
12562 or not $Info->{$TypeId}) {
12563 return ();
12564 }
12565 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012566 return %Type if(not $Type{"BaseType"});
12567 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012568 {
12569 if($Info->{$BTid}) {
12570 return %{$Info->{$BTid}};
12571 }
12572 else { # something is going wrong
12573 return ();
12574 }
12575 }
12576 else {
12577 return %Type;
12578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579}
12580
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012581sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012582{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012583 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012584 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012585 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12586 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587}
12588
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012589sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012590{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 my $Symbol = $_[0];
12592 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12593}
12594
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012595sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012596 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12597}
12598
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012599sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012601 my ($SInfo, $LibVersion) = @_;
12602
12603 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012605 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012606 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012607 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012608 return 1;
12609 }
12610 }
12611 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012612 if(my $ShortName = $SInfo->{"ShortName"})
12613 {
12614 if(index($ShortName,"<")!=-1
12615 and index($ShortName,">")!=-1) {
12616 return 1;
12617 }
12618 }
12619
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012620 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621}
12622
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012623sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012625 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012626 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012627 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012628 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012629 { # class specialization
12630 return 1;
12631 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012632 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012633 { # method specialization
12634 return 1;
12635 }
12636 }
12637 return 0;
12638}
12639
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012640sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012641{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012642 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012643
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012644 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645 { # non-public global data
12646 return 0;
12647 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012648
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012649 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012650 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012651 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012652 }
12653
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012654 if($Symbol=~/\A_Z/)
12655 {
12656 if($Symbol=~/[CD][3-4]E/) {
12657 return 0;
12658 }
12659 }
12660
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012661 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 { # support for old ABI dumps in --headers-only mode
12663 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12664 {
12665 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12666 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012667 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012668 if(not $PType or $PType eq "Unknown") {
12669 return 0;
12670 }
12671 }
12672 }
12673 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012674 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012675 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012676 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12677
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012678 if($SkipSymbols{$LibVersion}{$Symbol})
12679 { # user defined symbols to ignore
12680 return 0;
12681 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012682
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012683 if($SymbolsListPath and not $SymbolsList{$Symbol})
12684 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012685 if(not $TargetHeadersPath or not $Header
12686 or not is_target_header($Header, 1))
12687 { # -symbols-list | -headers-list
12688 return 0;
12689 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012690 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012691
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012692 if($AppPath and not $SymbolsList_App{$Symbol})
12693 { # user defined symbols (in application)
12694 return 0;
12695 }
12696
12697 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12698
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012699 if($ClassId)
12700 {
12701 if(not isTargetType($ClassId, $LibVersion)) {
12702 return 0;
12703 }
12704 }
12705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012706 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12707 if(not $NameSpace and $ClassId)
12708 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012709 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012710 }
12711 if($NameSpace)
12712 { # user defined namespaces to ignore
12713 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12714 return 0;
12715 }
12716 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12717 { # nested namespaces
12718 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12719 return 0;
12720 }
12721 }
12722 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012723 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012724 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012725 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012726 { # --skip-headers or <skip_headers> (not <skip_including>)
12727 if($Skip==1) {
12728 return 0;
12729 }
12730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012732 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012733 { # user defined types
12734 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12735
12736 if(not $TypesList{$CName})
12737 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012738 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12739 {
12740 $CName=~s/\A\Q$NS\E\:\://g;
12741 }
12742
12743 if(not $TypesList{$CName})
12744 {
12745 my $Found = 0;
12746
12747 while($CName=~s/\:\:.+?\Z//)
12748 {
12749 if($TypesList{$CName})
12750 {
12751 $Found = 1;
12752 last;
12753 }
12754 }
12755
12756 if(not $Found) {
12757 return 0;
12758 }
12759 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012760 }
12761 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012762
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012763 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12764 { # non-target symbols
12765 return 0;
12766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012769 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12770 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012771 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012772 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12773 { # inline virtual methods
12774 if($Type=~/InlineVirt/) {
12775 return 1;
12776 }
12777 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12778 if(not $Allocable)
12779 { # check bases
12780 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12781 {
12782 if(not isCopyingClass($DCId, $LibVersion))
12783 { # exists a derived class without default c-tor
12784 $Allocable=1;
12785 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012787 }
12788 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012789 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012790 return 0;
12791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012792 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012793 else
12794 { # inline non-virtual methods
12795 return 0;
12796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 }
12799 }
12800 return 1;
12801}
12802
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012803sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012804{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012805 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12807 {
12808 if(link_symbol($Symbol, 1, "+Deps"))
12809 { # linker can find a new symbol
12810 # in the old-version library
12811 # So, it's not a new symbol
12812 next;
12813 }
12814 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012815 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012816 next;
12817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012818 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012819 }
12820}
12821
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012822sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012823{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12826 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 if(link_symbol($Symbol, 2, "+Deps"))
12828 { # linker can find an old symbol
12829 # in the new-version library
12830 next;
12831 }
12832 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012833 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834 next;
12835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 }
12838}
12839
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012840sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012841{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 my $Level = $_[0];
12843 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844 { # checking added symbols
12845 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012846 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012847 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012851 { # checking removed symbols
12852 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012853 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012854 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 { # skip v-tables for templates, that should not be imported by applications
12856 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012857 if(my $CName = $VTableClass{$Symbol})
12858 {
12859 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12860 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012861 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012862 next;
12863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012864 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012865
12866 if($SkipSymbols{1}{$Symbol})
12867 { # user defined symbols to ignore
12868 next;
12869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 }
12871 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012872 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012873 }
12874 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12875 { # symbols for pure virtual methods cannot be called by clients
12876 next;
12877 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012878 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012879 }
12880}
12881
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012882sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012883{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012884 my ($LibVersion, $V) = @_;
12885 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12886 return $Cache{"checkDump"}{$LibVersion}{$V};
12887 }
12888 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012889}
12890
12891sub detectAdded_H($)
12892{
12893 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12895 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012896 if($Level eq "Source")
12897 { # remove symbol version
12898 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12899 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012900
12901 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12902 { # skip artificial constructors
12903 next;
12904 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012905 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012906 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12907 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012908 next;
12909 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012910 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012911 next;
12912 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012913 if(not defined $CompleteSignature{1}{$Symbol}
12914 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12915 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012916 if($UsedDump{2}{"SrcBin"})
12917 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012918 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012919 { # support for old and different (!) ABI dumps
12920 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12921 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012922 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012923 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012924 {
12925 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12926 {
12927 if($Lang eq "C")
12928 { # support for old ABI dumps: missed extern "C" functions
12929 next;
12930 }
12931 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012932 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012933 else
12934 {
12935 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012936 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012937 next;
12938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012939 }
12940 }
12941 }
12942 }
12943 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012944 }
12945 }
12946}
12947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012949{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012950 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012951 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12952 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012953 if($Level eq "Source")
12954 { # remove symbol version
12955 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12956 $Symbol=$SN;
12957 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012958 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12959 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 next;
12961 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012962 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012963 next;
12964 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012965 if(not defined $CompleteSignature{2}{$Symbol}
12966 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012967 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012968 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012970 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012971 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012972 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12973 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012974 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012975 if($CheckHeadersOnly)
12976 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012977 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12978 {
12979 if($Lang eq "C")
12980 { # support for old ABI dumps: missed extern "C" functions
12981 next;
12982 }
12983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012985 else
12986 {
12987 if(not link_symbol($Symbol, 1, "-Deps"))
12988 { # skip removed inline symbols
12989 next;
12990 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012991 }
12992 }
12993 }
12994 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012995 if(not checkDump(1, "2.15"))
12996 {
12997 if($Symbol=~/_IT_E\Z/)
12998 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12999 next;
13000 }
13001 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013002 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13003 {
13004 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13005 {
13006 if(defined $Constants{2}{$Short})
13007 {
13008 my $Val = $Constants{2}{$Short}{"Value"};
13009 if(defined $Func_ShortName{2}{$Val})
13010 { # old name defined to new
13011 next;
13012 }
13013 }
13014 }
13015
13016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013017 $RemovedInt{$Level}{$Symbol} = 1;
13018 if($Level eq "Source")
13019 { # search for a source-compatible equivalent
13020 setAlternative($Symbol, $Level);
13021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013022 }
13023 }
13024}
13025
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013026sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013027{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013028 my $Level = $_[0];
13029 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013030 { # checking added symbols
13031 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013032 next if($CompleteSignature{2}{$Symbol}{"Private"});
13033 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013034 if($Level eq "Binary")
13035 {
13036 if($CompleteSignature{2}{$Symbol}{"InLine"})
13037 {
13038 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13039 { # skip inline non-virtual functions
13040 next;
13041 }
13042 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013043 }
13044 else
13045 { # Source
13046 if($SourceAlternative_B{$Symbol}) {
13047 next;
13048 }
13049 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013050 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013052 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013053 { # checking removed symbols
13054 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013055 next if($CompleteSignature{1}{$Symbol}{"Private"});
13056 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013057 if($Level eq "Binary")
13058 {
13059 if($CompleteSignature{1}{$Symbol}{"InLine"})
13060 {
13061 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13062 { # skip inline non-virtual functions
13063 next;
13064 }
13065 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013066 }
13067 else
13068 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013069 if(my $Alt = $SourceAlternative{$Symbol})
13070 {
13071 if(defined $CompleteSignature{1}{$Alt}
13072 and $CompleteSignature{1}{$Symbol}{"Const"})
13073 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013074 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013075 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013076 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013077 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013078 }
13079 else
13080 { # do NOT show removed symbol
13081 next;
13082 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013083 }
13084 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 }
13087}
13088
13089sub addParamNames($)
13090{
13091 my $LibraryVersion = $_[0];
13092 return if(not keys(%AddIntParams));
13093 my $SecondVersion = $LibraryVersion==1?2:1;
13094 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13095 {
13096 next if(not keys(%{$AddIntParams{$Interface}}));
13097 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013098 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013099 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13100 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013101 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013102 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13103 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13104 {
13105 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13106 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13107 }
13108 }
13109 else {
13110 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13111 }
13112 }
13113 }
13114 }
13115}
13116
13117sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013118{ # detect changed typedefs to show
13119 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13121 {
13122 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013123 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13124 if(not $BName1 or isAnon($BName1)) {
13125 next;
13126 }
13127 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13128 if(not $BName2 or isAnon($BName2)) {
13129 next;
13130 }
13131 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013132 $ChangedTypedef{$Typedef} = 1;
13133 }
13134 }
13135}
13136
13137sub get_symbol_suffix($$)
13138{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013139 my ($Symbol, $Full) = @_;
13140 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013141 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013142 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013143 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013144 if(not $Full) {
13145 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13146 }
13147 return $Suffix;
13148}
13149
13150sub get_symbol_prefix($$)
13151{
13152 my ($Symbol, $LibVersion) = @_;
13153 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13154 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13155 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013156 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013157 }
13158 return $ShortName;
13159}
13160
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013161sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013162{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013163 my $Symbol = $_[0];
13164 my $PSymbol = $Symbol;
13165 if(not defined $CompleteSignature{2}{$PSymbol}
13166 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13167 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13168 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013169 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013171 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013173 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13174 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175 {
13176 if(defined $CompleteSignature{2}{$PSymbol}
13177 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13178 {
13179 $SourceAlternative{$Symbol} = $PSymbol;
13180 $SourceAlternative_B{$PSymbol} = $Symbol;
13181 if(not defined $CompleteSignature{1}{$PSymbol}
13182 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13183 $SourceReplacement{$Symbol} = $PSymbol;
13184 }
13185 }
13186 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013187 }
13188 else
13189 {
13190 foreach my $Sp ("KV", "VK", "K", "V")
13191 {
13192 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13193 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13194 {
13195 if(defined $CompleteSignature{2}{$PSymbol}
13196 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13197 {
13198 $SourceAlternative{$Symbol} = $PSymbol;
13199 $SourceAlternative_B{$PSymbol} = $Symbol;
13200 if(not defined $CompleteSignature{1}{$PSymbol}
13201 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13202 $SourceReplacement{$Symbol} = $PSymbol;
13203 }
13204 }
13205 }
13206 $PSymbol = $Symbol;
13207 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013208 }
13209 }
13210 }
13211 return "";
13212}
13213
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013214sub getSymKind($$)
13215{
13216 my ($Symbol, $LibVersion) = @_;
13217 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13218 {
13219 return "Global_Data";
13220 }
13221 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13222 {
13223 return "Method";
13224 }
13225 return "Function";
13226}
13227
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013228sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013229{
13230 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013231 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013232
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 mergeBases($Level);
13234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013235 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013237 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013238 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 next;
13240 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013241 if(defined $CompleteSignature{1}{$Symbol}
13242 and $CompleteSignature{1}{$Symbol}{"Header"})
13243 { # double-check added symbol
13244 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013246 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013247 next;
13248 }
13249 if($Symbol=~/\A(_Z|\?)/)
13250 { # C++
13251 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13252 }
13253 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13254 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013255 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13256 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013257 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013259 {
13260 if($TName_Tid{1}{$AffectedClass_Name})
13261 { # class should exist in previous version
13262 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13263 { # old v-table is NOT copied by old applications
13264 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13265 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013266 "Target"=>get_Signature($Symbol, 2),
13267 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013268 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013271 }
13272 }
13273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013274 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13275 { # check all removed exported symbols
13276 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 next;
13278 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013279 if(defined $CompleteSignature{2}{$Symbol}
13280 and $CompleteSignature{2}{$Symbol}{"Header"})
13281 { # double-check removed symbol
13282 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013283 }
13284 if($CompleteSignature{1}{$Symbol}{"Private"})
13285 { # skip private methods
13286 next;
13287 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013288 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013289 next;
13290 }
13291 $CheckedSymbols{$Level}{$Symbol} = 1;
13292 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13293 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013294 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13295 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013296 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013297 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13298 {
13299 if($TName_Tid{2}{$AffectedClass_Name})
13300 { # class should exist in newer version
13301 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13302 { # old v-table is NOT copied by old applications
13303 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13304 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013305 "Target"=>get_Signature($OverriddenMethod, 1),
13306 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013307 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013310 }
13311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013312 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013313 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013314 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013315 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013316 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013317 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013319 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013321 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013322 {
13323 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13324 "Target"=>$tr_name{$Symbol},
13325 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013326 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013328 else
13329 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013330 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013331 "Target"=>$tr_name{$Symbol},
13332 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013333 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013334 }
13335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013336 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013338 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013339 {
13340 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13341 "Target"=>$tr_name{$Symbol},
13342 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 else
13346 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013347 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 "Target"=>$tr_name{$Symbol},
13349 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
13352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13354 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13355 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13356 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13357 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 {
13359 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013360 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 $ProblemType = "Global_Data_Symbol_Changed_Type";
13362 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13364 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013365 "Old_Type"=>$RTName1,
13366 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013368 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013369 }
13370 }
13371 }
13372 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013377 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013378 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013379 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013380 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13381 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013382 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013383 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013384 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013385 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013386 }
13387 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13389 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013390 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013391 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013392 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013393 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013394 }
13395 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013396 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013397 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013398 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013399 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013401 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013402 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013403 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013404 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013406 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013407 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013408 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013411 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013412 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013413 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013414 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013415 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013417 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013420 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421 { # "volatile" to non-"volatile"
13422
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013423 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013425 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013426 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013427 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013428 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013429 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013430 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013431 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013432 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013435 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013436 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013437 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013438 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013440 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13441 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013442 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013444 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013445 }
13446 }
13447 }
13448 }
13449 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13451 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013452 $CurrentSymbol = $Symbol;
13453
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013454 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13455 if($Level eq "Source")
13456 { # remove symbol version
13457 $Symbol=$SN;
13458 }
13459 else
13460 { # Binary
13461 if(not $SV)
13462 { # symbol without version
13463 if(my $VSym = $SymVer{1}{$Symbol})
13464 { # the symbol is linked with versioned symbol
13465 if($CompleteSignature{2}{$VSym}{"MnglName"})
13466 { # show report for symbol@ver only
13467 next;
13468 }
13469 elsif(not link_symbol($VSym, 2, "-Deps"))
13470 { # changed version: sym@v1 to sym@v2
13471 # do NOT show report for symbol
13472 next;
13473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013474 }
13475 }
13476 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013477 my $PSymbol = $Symbol;
13478 if($Level eq "Source"
13479 and my $S = $SourceReplacement{$Symbol})
13480 { # take a source-compatible replacement function
13481 $PSymbol = $S;
13482 }
13483 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013484 { # private symbols
13485 next;
13486 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013487 if(not defined $CompleteSignature{1}{$Symbol}
13488 or not defined $CompleteSignature{2}{$PSymbol})
13489 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013490 next;
13491 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013492 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13493 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13494 { # no mangled name
13495 next;
13496 }
13497 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13498 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 { # without a header
13500 next;
13501 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013502
13503 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13504 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13505 { # became pure
13506 next;
13507 }
13508 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13509 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13510 { # became non-pure
13511 next;
13512 }
13513
13514 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13515 { # exported, target, inline virtual and pure virtual
13516 next;
13517 }
13518 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13519 { # exported, target, inline virtual and pure virtual
13520 next;
13521 }
13522
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013523 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013524 {
13525 if($CompleteSignature{1}{$Symbol}{"Data"}
13526 and $CompleteSignature{2}{$PSymbol}{"Data"})
13527 {
13528 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13529 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13530 if(defined $Value1)
13531 {
13532 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13533 if(defined $Value2)
13534 {
13535 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13536 if($Value1 ne $Value2)
13537 {
13538 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13539 "Old_Value"=>$Value1,
13540 "New_Value"=>$Value2,
13541 "Target"=>get_Signature($Symbol, 1) );
13542 }
13543 }
13544 }
13545 }
13546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013547
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013548 if($CompleteSignature{2}{$PSymbol}{"Private"})
13549 {
13550 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13551 "Target"=>get_Signature_M($PSymbol, 2) );
13552 }
13553 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13554 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13555 {
13556 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13557 "Target"=>get_Signature_M($PSymbol, 2) );
13558 }
13559 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13560 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13561 {
13562 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13563 "Target"=>get_Signature_M($PSymbol, 2) );
13564 }
13565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013566 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013567 mergeVirtualTables($Symbol, $Level);
13568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013569 if($COMPILE_ERRORS)
13570 { # if some errors occurred at the compiling stage
13571 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013573 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013574 { # missed information about parameters in newer version
13575 next;
13576 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013577 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013578 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013579 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013580 next;
13581 }
13582 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013585 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013586 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13587 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013588 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13589 "Target"=>get_Signature($Symbol, 1)
13590 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013592 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013593 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13594 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013595 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013596 "Target"=>get_Signature($Symbol, 1)
13597 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013599 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13600 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013603 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013604 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13605 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13606 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013607 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013608 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013609 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13610 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013611 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013612 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013613 my $ProblemType = "Virtual_Method_Position";
13614 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13615 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013617 if(isUsedClass($Class_Id, 1, $Level))
13618 {
13619 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013620 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013621 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013622 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13623 next;
13624 }
13625 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013626 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013627 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13628 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013629 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013631 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013633 }
13634 }
13635 }
13636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013637 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13638 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013639 { # do NOT check type changes in pure virtuals
13640 next;
13641 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013642 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013643 if($Symbol=~/\A(_Z|\?)/
13644 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013646 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013648 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013649 }
13650 }
13651 else
13652 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013653 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013654 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013655 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013656 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13657 last if($PType2_Name eq "...");
13658 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13659 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013660 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013661 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013662 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013663 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13664 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013665 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13666 $ParamPos_Prev = "lost";
13667 }
13668 }
13669 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013670 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 }
13672 if($ParamPos_Prev eq "lost")
13673 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013674 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013675 {
13676 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013677 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 $ProblemType = "Added_Unnamed_Parameter";
13679 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013680 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013681 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013682 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013683 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013684 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013685 }
13686 else
13687 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013688 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013689 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013690 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013691 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13692 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013696 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013697 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013698 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013699 "Param_Type"=>$PType2_Name,
13700 "Old_Value"=>$PName_Old,
13701 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013702 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 }
13704 }
13705 else
13706 {
13707 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013708 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 $ProblemType = "Added_Middle_Unnamed_Parameter";
13710 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013711 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013712 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013713 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013714 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013715 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 }
13717 }
13718 }
13719 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013720 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013721 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013722 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013723 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013724 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013725 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013726 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013727 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013728 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013729 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13730 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013731 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013732 }
13733 }
13734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013735 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013736 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013737 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013738 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13739 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013740 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13741 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013742 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013743 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013744 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013745 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13746 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013747 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13748 $ParamPos_New = "lost";
13749 }
13750 }
13751 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013752 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013753 }
13754 if($ParamPos_New eq "lost")
13755 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013756 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013757 {
13758 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013759 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 $ProblemType = "Removed_Unnamed_Parameter";
13761 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013762 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013763 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013764 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013765 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013766 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013767 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013768 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013769 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013770 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013771 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013772 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013773 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013774 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013775 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013776 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013777 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013778 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013779 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013780 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013781 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013782 "Old_Value"=>$PName,
13783 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013784 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013785 }
13786 }
13787 else
13788 {
13789 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013790 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013791 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13792 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013793 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013794 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013795 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013796 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013797 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013798 }
13799 }
13800 }
13801 }
13802 }
13803 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013804 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13805 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013806 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013807
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013808 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013810 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13811 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013812 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013813
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013814 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013815 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013816 if($SubProblemType eq "Return_Type_And_Size") {
13817 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13818 }
13819 elsif($SubProblemType eq "Return_Type_Format") {
13820 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13821 }
13822 else {
13823 $ProblemTypes{"Global_Data_Type"} = 1;
13824 }
13825
13826 # quals
13827 if($SubProblemType eq "Return_Type"
13828 or $SubProblemType eq "Return_Type_And_Size"
13829 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013831 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13832 { # const to non-const
13833 if($RR==2) {
13834 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13835 }
13836 else {
13837 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13838 }
13839 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013840 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013841 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13842 { # non-const to const
13843 if($RA==2) {
13844 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13845 }
13846 else {
13847 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13848 }
13849 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013850 }
13851 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 }
13853 else
13854 {
13855 # quals
13856 if($SubProblemType eq "Return_Type"
13857 or $SubProblemType eq "Return_Type_And_Size"
13858 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013859 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013860 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013861 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013862 if(addedQual($Old_Value, $New_Value, "volatile"))
13863 {
13864 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13865 if($Level ne "Source"
13866 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13867 $ProblemTypes{"Return_Type"} = 1;
13868 }
13869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013871 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13872 {
13873 if($RA==2) {
13874 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13875 }
13876 else {
13877 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13878 }
13879 if($Level ne "Source"
13880 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13881 $ProblemTypes{"Return_Type"} = 1;
13882 }
13883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013884 }
13885 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013886 if($Level eq "Binary"
13887 and not $CompleteSignature{1}{$Symbol}{"Data"})
13888 {
13889 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13890 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13891 { # if one of the architectures is unknown
13892 # then set other arhitecture to unknown too
13893 ($Arch1, $Arch2) = ("unknown", "unknown");
13894 }
13895 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013896 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013897 {
13898 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13899 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13900 }
13901 else
13902 {
13903 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13904 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13905 }
13906
13907 if($SubProblemType eq "Return_Type_Became_Void")
13908 {
13909 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13910 { # parameters stack has been affected
13911 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013912 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013913 }
13914 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013915 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013916 }
13917 }
13918 }
13919 elsif($SubProblemType eq "Return_Type_From_Void")
13920 {
13921 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13922 { # parameters stack has been affected
13923 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013924 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013925 }
13926 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013927 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013928 }
13929 }
13930 }
13931 elsif($SubProblemType eq "Return_Type"
13932 or $SubProblemType eq "Return_Type_And_Size"
13933 or $SubProblemType eq "Return_Type_Format")
13934 {
13935 if($Conv1{"Method"} ne $Conv2{"Method"})
13936 {
13937 if($Conv1{"Method"} eq "stack")
13938 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013939 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013940 }
13941 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013942 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013943 }
13944 }
13945 else
13946 {
13947 if($Conv1{"Method"} eq "reg")
13948 {
13949 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13950 {
13951 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013952 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013953 }
13954 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013955 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013956 }
13957 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013958 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013959 }
13960 }
13961 }
13962 }
13963 }
13964 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013965
13966 if(not keys(%ProblemTypes))
13967 { # default
13968 $ProblemTypes{$SubProblemType} = 1;
13969 }
13970
13971 foreach my $ProblemType (keys(%ProblemTypes))
13972 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013973 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013975 }
13976 if($ReturnType1_Id and $ReturnType2_Id)
13977 {
13978 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013979 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13980
13981 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013982
13983 if($CompleteSignature{1}{$Symbol}{"Data"})
13984 {
13985 if($Level eq "Binary")
13986 {
13987 if(get_PLevel($ReturnType1_Id, 1)==0)
13988 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013989 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013990 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013991
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013992 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13993 {
13994 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013995 {
13996 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13997 {
13998 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13999 last;
14000 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014001 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014002 }
14003 }
14004 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014005 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014006 {
14007 if(defined $GlobalDataObject{1}{$Symbol}
14008 and defined $GlobalDataObject{2}{$Symbol})
14009 {
14010 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14011 my $New_Size = $GlobalDataObject{2}{$Symbol};
14012 if($Old_Size!=$New_Size)
14013 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014014 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014015 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014016 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014017 }
14018 }
14019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014020 }
14021 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014022
14023 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014024 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014025 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014026 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014027 my $NewLocation = "retval";
14028 if($SubLocation and $SubLocation ne "retval") {
14029 $NewLocation = "retval->".$SubLocation;
14030 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014031 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14032 }
14033 }
14034
14035 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14036 {
14037 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14038 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014039 my $NewLocation = "retval";
14040 if($SubLocation and $SubLocation ne "retval") {
14041 $NewLocation = "retval->".$SubLocation;
14042 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014043 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014044 }
14045 }
14046 }
14047
14048 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014049 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14050 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14051 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014052 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014054 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14055 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056 if($ThisPtr1_Id and $ThisPtr2_Id)
14057 {
14058 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014059 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14060 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014061 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014062 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014063 {
14064 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014065 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014066 }
14067 }
14068 }
14069 }
14070 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014071 if($Level eq "Binary") {
14072 mergeVTables($Level);
14073 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014074 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14075 $CheckedSymbols{$Level}{$Symbol} = 1;
14076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014077}
14078
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014079sub rmQuals($$)
14080{
14081 my ($Value, $Qual) = @_;
14082 if(not $Qual) {
14083 return $Value;
14084 }
14085 if($Qual eq "all")
14086 { # all quals
14087 $Qual = "const|volatile|restrict";
14088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014089 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014090 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014091 }
14092 return $Value;
14093}
14094
14095sub cmpBTypes($$$$)
14096{
14097 my ($T1, $T2, $V1, $V2) = @_;
14098 $T1 = uncover_typedefs($T1, $V1);
14099 $T2 = uncover_typedefs($T2, $V2);
14100 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14101}
14102
14103sub addedQual($$$)
14104{
14105 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014106 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014107}
14108
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014109sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014110{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014111 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014112 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014113}
14114
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014115sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014116{
14117 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14118 $Old_Value = uncover_typedefs($Old_Value, $V1);
14119 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014120
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014121 if($Old_Value eq $New_Value)
14122 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014123 return 0;
14124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014125 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014126 { # without a qual
14127 return 0;
14128 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014129 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014130 { # became non-qual
14131 return 1;
14132 }
14133 else
14134 {
14135 my @BQ1 = getQualModel($Old_Value, $Qual);
14136 my @BQ2 = getQualModel($New_Value, $Qual);
14137 foreach (0 .. $#BQ1)
14138 { # removed qual
14139 if($BQ1[$_]==1
14140 and $BQ2[$_]!=1)
14141 {
14142 return 2;
14143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014144 }
14145 }
14146 return 0;
14147}
14148
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149sub getQualModel($$)
14150{
14151 my ($Value, $Qual) = @_;
14152 if(not $Qual) {
14153 return $Value;
14154 }
14155
14156 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014157 while($Value=~/(\w+)/)
14158 {
14159 my $W = $1;
14160
14161 if($W eq $Qual) {
14162 $Value=~s/\b$W\b/\@/g;
14163 }
14164 else {
14165 $Value=~s/\b$W\b//g;
14166 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014167 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014168
14169 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014170 $Value=~s/[^\*\&\w]+//g;
14171
14172 # modeling
14173 # int*const*const == 011
14174 # int**const == 001
14175 my @Model = ();
14176 my @Elems = split(/[\*\&]/, $Value);
14177 if(not @Elems) {
14178 return (0);
14179 }
14180 foreach (@Elems)
14181 {
14182 if($_ eq $Qual) {
14183 push(@Model, 1);
14184 }
14185 else {
14186 push(@Model, 0);
14187 }
14188 }
14189
14190 return @Model;
14191}
14192
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014193my %StringTypes = map {$_=>1} (
14194 "char*",
14195 "char const*"
14196);
14197
14198my %CharTypes = map {$_=>1} (
14199 "char",
14200 "char const"
14201);
14202
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014203sub showVal($$$)
14204{
14205 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014206 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014207 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014208 if(substr($Value, 0, 2) eq "_Z")
14209 {
14210 if(my $Unmangled = $tr_name{$Value}) {
14211 return $Unmangled;
14212 }
14213 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014214 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014215 { # strings
14216 return "\"$Value\"";
14217 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014218 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014219 { # characters
14220 return "\'$Value\'";
14221 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014222 if($Value eq "")
14223 { # other
14224 return "\'\'";
14225 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014226 return $Value;
14227}
14228
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014229sub getRegs($$$)
14230{
14231 my ($LibVersion, $Symbol, $Pos) = @_;
14232
14233 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14234 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014235 my %Regs = ();
14236 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14237 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014238 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014239 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14240 }
14241 }
14242
14243 return join(", ", sort keys(%Regs));
14244 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014245 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14246 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14247 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14248 {
14249 return "unknown";
14250 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014251
14252 return undef;
14253}
14254
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014255sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014256{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014257 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014258 if(not $Symbol) {
14259 return;
14260 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014261 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14262 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14263 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14264 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014265 if(not $PType1_Id
14266 or not $PType2_Id) {
14267 return;
14268 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014269
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014270 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014271 { # do not merge "this"
14272 if($PName1 eq "this" or $PName2 eq "this") {
14273 return;
14274 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014275 }
14276
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014277 my %Type1 = get_Type($PType1_Id, 1);
14278 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014279
14280 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14281
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014282 my %BaseType1 = get_BaseType($PType1_Id, 1);
14283 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014284
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014285 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014286
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014287 if($Level eq "Binary")
14288 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014289 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014290 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14291 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14292 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14293 {
14294 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014295 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014296 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014297 }
14298 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14299 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14300 {
14301 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014302 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014303 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014305 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014306
14307 if(defined $UsedDump{1}{"DWARF"}
14308 and defined $UsedDump{2}{"DWARF"})
14309 {
14310 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14311 {
14312 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14313 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014314
14315 if($Old_Regs ne "unknown"
14316 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014317 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014318 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014319 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014320 if($Old_Regs ne $New_Regs)
14321 {
14322 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14323 "Target"=>$PName1,
14324 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14325 "Old_Value"=>$Old_Regs,
14326 "New_Value"=>$New_Regs );
14327 }
14328 }
14329 elsif($Old_Regs and not $New_Regs)
14330 {
14331 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014332 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014333 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014334 "Old_Value"=>$Old_Regs );
14335 }
14336 elsif(not $Old_Regs and $New_Regs)
14337 {
14338 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14339 "Target"=>$PName1,
14340 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014341 "New_Value"=>$New_Regs );
14342 }
14343 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014344
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014345 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14346 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14347 {
14348 if($Old_Offset ne $New_Offset)
14349 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014350 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14351 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14352
14353 $Old_Offset = $Old_Offset - $Start1;
14354 $New_Offset = $New_Offset - $Start2;
14355
14356 if($Old_Offset ne $New_Offset)
14357 {
14358 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14359 "Target"=>$PName1,
14360 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14361 "Old_Value"=>$Old_Offset,
14362 "New_Value"=>$New_Offset );
14363 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014364 }
14365 }
14366 }
14367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014368 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014369 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14370 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014371 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014372 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014373 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14374 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014375 if(not checkDump(1, "2.13")
14376 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014377 { # support for old ABI dumps
14378 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014380 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014381 and $Value_Old eq "false" and $Value_New eq "0")
14382 { # int class::method ( bool p = 0 );
14383 # old ABI dumps: "false"
14384 # new ABI dumps: "0"
14385 $Value_Old = "0";
14386 }
14387 }
14388 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014389 if(not checkDump(1, "2.18")
14390 and checkDump(2, "2.18"))
14391 { # support for old ABI dumps
14392 if(not defined $Value_Old
14393 and substr($Value_New, 0, 2) eq "_Z") {
14394 $Value_Old = $Value_New;
14395 }
14396 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014397 if(defined $Value_Old)
14398 {
14399 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14400 if(defined $Value_New)
14401 {
14402 $Value_New = showVal($Value_New, $PType2_Id, 2);
14403 if($Value_Old ne $Value_New)
14404 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014405 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014406 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014407 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014408 "Old_Value"=>$Value_Old,
14409 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014410 }
14411 }
14412 else
14413 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014414 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014415 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014416 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014417 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014418 }
14419 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014420 elsif(defined $Value_New)
14421 {
14422 $Value_New = showVal($Value_New, $PType2_Id, 2);
14423 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14424 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014425 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014426 "New_Value"=>$Value_New );
14427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014428 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014429
14430 if($ChkRnmd)
14431 {
14432 if($PName1 and $PName2 and $PName1 ne $PName2
14433 and $PType1_Id!=-1 and $PType2_Id!=-1
14434 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14435 { # except unnamed "..." value list (Id=-1)
14436 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14437 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014438 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014439 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14440 "Old_Value"=>$PName1,
14441 "New_Value"=>$PName2,
14442 "New_Signature"=>get_Signature($Symbol, 2) );
14443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014444 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014446 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014447 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014449 foreach my $SubProblemType (keys(%SubProblems))
14450 { # add new problems, remove false alarms
14451 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14452 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014453
14454 # quals
14455 if($SubProblemType eq "Parameter_Type"
14456 or $SubProblemType eq "Parameter_Type_And_Size"
14457 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014458 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014459 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014460 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014461 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014462 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014463 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014464 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14465 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14466 }
14467 }
14468 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14469 {
14470 if(removedQual($Old_Value, $New_Value, "volatile")) {
14471 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014472 }
14473 }
14474 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14475 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14476 { # int to "int const"
14477 delete($SubProblems{$SubProblemType});
14478 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014479 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014480 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14481 { # "int const" to int
14482 delete($SubProblems{$SubProblemType});
14483 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014484 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14485 { # "const" to non-"const"
14486 if($RR==2) {
14487 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14488 }
14489 else {
14490 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14491 }
14492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014493 }
14494 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014495
14496 if($Level eq "Source")
14497 {
14498 foreach my $SubProblemType (keys(%SubProblems))
14499 {
14500 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14501 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14502
14503 if($SubProblemType eq "Parameter_Type")
14504 {
14505 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14506 delete($SubProblems{$SubProblemType});
14507 }
14508 }
14509 }
14510 }
14511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 foreach my $SubProblemType (keys(%SubProblems))
14513 { # modify/register problems
14514 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14515 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014516 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14517 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014519 my $NewProblemType = $SubProblemType;
14520 if($Old_Value eq "..." and $New_Value ne "...")
14521 { # change from "..." to "int"
14522 if($ParamPos1==0)
14523 { # ISO C requires a named argument before "..."
14524 next;
14525 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014526 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014527 }
14528 elsif($New_Value eq "..." and $Old_Value ne "...")
14529 { # change from "int" to "..."
14530 if($ParamPos2==0)
14531 { # ISO C requires a named argument before "..."
14532 next;
14533 }
14534 $NewProblemType = "Parameter_Became_VaList";
14535 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014536 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014537 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 {
14539 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014540 if($Arch1 eq "unknown"
14541 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014542 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014543 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014544 ($Arch1, $Arch2) = ("unknown", "unknown");
14545 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014546 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014547 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014548 { # real
14549 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14550 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14551 }
14552 else
14553 { # model
14554 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14555 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14556 }
14557 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014558 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014559 if($Conv1{"Method"} eq "stack")
14560 {
14561 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14562 $NewProblemType = "Parameter_Type_And_Stack";
14563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014564 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014565 elsif($Conv1{"Method"} eq "reg")
14566 {
14567 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14568 $NewProblemType = "Parameter_Type_And_Register";
14569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014570 }
14571 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014572 elsif($Conv1{"Method"} ne "unknown"
14573 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014575 if($Conv1{"Method"} eq "stack") {
14576 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014578 elsif($Conv1{"Method"} eq "register") {
14579 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580 }
14581 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014582 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14583 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014585 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014586 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014587 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014588 "New_Signature"=>get_Signature($Symbol, 2) );
14589 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014592 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014594 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014595 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14596 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014597 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014598 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014599 {
14600 my $NewProblemType = $SubProblemType;
14601 if($SubProblemType eq "DataType_Size")
14602 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014603 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014604 { # stack has been affected
14605 $NewProblemType = "DataType_Size_And_Stack";
14606 }
14607 }
14608 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014609 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014610 }
14611 }
14612}
14613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614sub find_ParamPair_Pos_byName($$$)
14615{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014616 my ($Name, $Symbol, $LibVersion) = @_;
14617 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014619 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14620 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 {
14622 return $ParamPos;
14623 }
14624 }
14625 return "lost";
14626}
14627
14628sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14629{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014630 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014632 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014633 {
14634 next if($Order eq "backward" and $ParamPos>$MediumPos);
14635 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014636 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14637 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014638 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 push(@Positions, $ParamPos);
14640 }
14641 }
14642 return @Positions;
14643}
14644
14645sub getTypeIdByName($$)
14646{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014647 my ($TypeName, $LibVersion) = @_;
14648 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649}
14650
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014651sub diffTypes($$$)
14652{
14653 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14654 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14655 }
14656 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14657 { # skip recursive declarations
14658 return 0;
14659 }
14660
14661 pushType($_[0], $_[1], \@RecurTypes_Diff);
14662 my $Diff = diffTypes_I(@_);
14663 pop(@RecurTypes_Diff);
14664
14665 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14666}
14667
14668sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014670 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014671
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014672 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14673 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014674
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014675 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14676 { # equal types
14677 return 0;
14678 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014679 if($Type1_Pure{"Name"} eq "void")
14680 { # from void* to something
14681 return 0;
14682 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014683 if($Type2_Pure{"Name"} eq "void")
14684 { # from something to void*
14685 return 0;
14686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014687 if($Type1_Pure{"Name"}=~/\*/
14688 or $Type2_Pure{"Name"}=~/\*/)
14689 { # compared in detectTypeChange()
14690 return 0;
14691 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014692
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014693 my %FloatType = map {$_=>1} (
14694 "float",
14695 "double",
14696 "long double"
14697 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014698
14699 my $T1 = $Type1_Pure{"Type"};
14700 my $T2 = $Type2_Pure{"Type"};
14701
14702 if($T1 eq "Struct"
14703 and $T2 eq "Class")
14704 { # compare as data structures
14705 $T2 = "Struct";
14706 }
14707
14708 if($T1 eq "Class"
14709 and $T2 eq "Struct")
14710 { # compare as data structures
14711 $T1 = "Struct";
14712 }
14713
14714 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014715 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014716 if($T1 eq "Intrinsic"
14717 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014718 { # "int" to "enum"
14719 return 0;
14720 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014721 elsif($T2 eq "Intrinsic"
14722 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014723 { # "enum" to "int"
14724 return 0;
14725 }
14726 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014727 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014728 # ...
14729 return 1;
14730 }
14731 }
14732 else
14733 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014734 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 {
14736 if($FloatType{$Type1_Pure{"Name"}}
14737 or $FloatType{$Type2_Pure{"Name"}})
14738 { # "float" to "double"
14739 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014740 if($Level eq "Source")
14741 { # Safe
14742 return 0;
14743 }
14744 else {
14745 return 1;
14746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014747 }
14748 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014749 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014750 {
14751 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14752 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014753 if(not @Membs1
14754 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014755 { # private
14756 return 0;
14757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758 if($#Membs1!=$#Membs2)
14759 { # different number of elements
14760 return 1;
14761 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014762 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014763 {
14764 foreach my $Pos (@Membs1)
14765 { # compare elements by name and value
14766 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14767 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14768 { # different names
14769 return 1;
14770 }
14771 }
14772 }
14773 else
14774 {
14775 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014776 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014777 if($Level eq "Source")
14778 {
14779 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14780 { # different names
14781 return 1;
14782 }
14783 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014784
14785 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14786 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14787
14788 if($MT1{"Name"} ne $MT2{"Name"}
14789 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14790 {
14791 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14792 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14793
14794 if($PL1 ne $PL2)
14795 { # different pointer level
14796 return 1;
14797 }
14798
14799 # compare base types
14800 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14801 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14802
14803 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14804 { # different types
14805 return 1;
14806 }
14807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014808 }
14809 }
14810 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014811 else
14812 {
14813 # TODO: arrays, etc.
14814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014815 }
14816 return 0;
14817}
14818
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014819sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014820{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014821 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014822 if(not $Type1_Id or not $Type2_Id) {
14823 return ();
14824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014825 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014826 my %Type1 = get_Type($Type1_Id, 1);
14827 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014828 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14829 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014830
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014831 if(defined $SkipTypedefUncover)
14832 {
14833 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14834 return ();
14835 }
14836
14837 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14838 return ();
14839 }
14840 }
14841
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014842 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14843 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 +040014844
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014845 if(defined $UsedDump{1}{"DWARF"})
14846 {
14847 if($Type1_Pure{"Name"} eq "__unknown__"
14848 or $Type2_Pure{"Name"} eq "__unknown__"
14849 or $Type1_Base{"Name"} eq "__unknown__"
14850 or $Type2_Base{"Name"} eq "__unknown__")
14851 { # Error ABI dump
14852 return ();
14853 }
14854 }
14855
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014856 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14857 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014858 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14859 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14860 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14861 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14862 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14863 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14864 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014865 if($Type1{"Name"} eq $Type2{"Name"})
14866 {
14867 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14868 { # will be reported in mergeTypes() as typedef problem
14869 return ();
14870 }
14871 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14872 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14873 if(%Typedef_1 and %Typedef_2)
14874 {
14875 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14876 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14877 { # const Typedef
14878 return ();
14879 }
14880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014881 }
14882 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14883 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014884 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014885 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14886 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014887 {
14888 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14889 "Old_Value"=>$Type1_Base{"Name"},
14890 "New_Value"=>$Type2_Base{"Name"},
14891 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014892 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014893 }
14894 else
14895 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014896 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014897 { # format change
14898 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14899 "Old_Value"=>$Type1_Base{"Name"},
14900 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014901 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014902 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014903 }
14904 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14905 {
14906 %{$LocalProblems{$Prefix."_BaseType"}}=(
14907 "Old_Value"=>$Type1_Base{"Name"},
14908 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014909 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014910 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014911 }
14912 }
14913 }
14914 }
14915 elsif($Type1{"Name"} ne $Type2{"Name"})
14916 { # type change
14917 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14918 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014919 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 and $Type1_Pure{"Name"} eq "void")
14921 {
14922 %{$LocalProblems{"Return_Type_From_Void"}}=(
14923 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014924 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014926 elsif($Prefix eq "Return"
14927 and $Type2_Pure{"Name"} eq "void")
14928 {
14929 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14930 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014931 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014933 else
14934 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014935 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014936 and $Type1{"Size"} and $Type2{"Size"}
14937 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014938 {
14939 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14940 "Old_Value"=>$Type1{"Name"},
14941 "New_Value"=>$Type2{"Name"},
14942 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014943 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014944 }
14945 else
14946 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014947 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014948 { # format change
14949 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14950 "Old_Value"=>$Type1{"Name"},
14951 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014952 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014953 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 }
14955 elsif(tNameLock($Type1_Id, $Type2_Id))
14956 { # FIXME: correct this condition
14957 %{$LocalProblems{$Prefix."_Type"}}=(
14958 "Old_Value"=>$Type1{"Name"},
14959 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014960 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014961 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
14963 }
14964 }
14965 }
14966 }
14967 if($Type1_PLevel!=$Type2_PLevel)
14968 {
14969 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14970 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14971 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014972 if($Level eq "Source")
14973 {
14974 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014975 "Old_Value"=>$Type1_PLevel,
14976 "New_Value"=>$Type2_PLevel);
14977 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014978 else
14979 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014980 if($Type2_PLevel>$Type1_PLevel)
14981 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014982 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14983 "Old_Value"=>$Type1_PLevel,
14984 "New_Value"=>$Type2_PLevel);
14985 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014986 else
14987 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014988 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14989 "Old_Value"=>$Type1_PLevel,
14990 "New_Value"=>$Type2_PLevel);
14991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 }
14993 }
14994 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014995 if($Type1_Pure{"Type"} eq "Array"
14996 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997 { # base_type[N] -> base_type[N]
14998 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014999 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 foreach my $SubProblemType (keys(%SubProblems))
15001 {
15002 $SubProblemType=~s/_Type/_BaseType/g;
15003 next if(defined $LocalProblems{$SubProblemType});
15004 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
15005 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
15006 }
15007 }
15008 }
15009 return %LocalProblems;
15010}
15011
15012sub tNameLock($$)
15013{
15014 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015015 my $Changed = 0;
15016 if(differentDumps("G"))
15017 { # different GCC versions
15018 $Changed = 1;
15019 }
15020 elsif(differentDumps("V"))
15021 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015022 if(not checkDump(1, "2.20")
15023 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015024 { # latest names update
15025 # 2.6: added restrict qualifier
15026 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015027 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015028 $Changed = 1;
15029 }
15030 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015031
15032 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15033 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15034
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015035 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15036 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15037
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015038 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015040 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015041 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015042 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015043 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015044 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015045 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015046 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015047 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015048 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15049 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15050 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015051 { # equal base types
15052 return 0;
15053 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015054
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015055 if(not checkDump(1, "2.13")
15056 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015057 { # broken array names in ABI dumps < 2.13
15058 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015059 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060 return 0;
15061 }
15062 }
15063
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015064 if(not checkDump(1, "2.6")
15065 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015066 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015067 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015068 and $TN2=~/\brestrict\b/) {
15069 return 0;
15070 }
15071 }
15072
15073 if(not checkDump(1, "2.20")
15074 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015075 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015076 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15077 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015078 return 0;
15079 }
15080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015081 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015082 else
15083 {
15084 # typedef struct {...} type_t
15085 # typedef struct type_t {...} type_t
15086 if(index($TN1, " ".$TN2)!=-1)
15087 {
15088 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15089 return 0;
15090 }
15091 }
15092 if(index($TN2, " ".$TN1)!=-1)
15093 {
15094 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15095 return 0;
15096 }
15097 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015098
15099 if($TT1 eq "FuncPtr"
15100 and $TT2 eq "FuncPtr")
15101 {
15102 my $TN1_C = $TN1;
15103 my $TN2_C = $TN2;
15104
15105 $TN1_C=~s/\b(struct|union) //g;
15106 $TN2_C=~s/\b(struct|union) //g;
15107
15108 if($TN1_C eq $TN2_C) {
15109 return 0;
15110 }
15111 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015112 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015113
15114 my ($N1, $N2) = ($TN1, $TN2);
15115 $N1=~s/\b(struct|union) //g;
15116 $N2=~s/\b(struct|union) //g;
15117
15118 if($N1 eq $N2)
15119 { # QList<struct QUrl> and QList<QUrl>
15120 return 0;
15121 }
15122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123 return 1;
15124}
15125
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015126sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015127{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015128 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015129 if(defined $Cache{"differentDumps"}{$Check}) {
15130 return $Cache{"differentDumps"}{$Check};
15131 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015132 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015133 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015134 if($Check eq "G")
15135 {
15136 if(getGccVersion(1) ne getGccVersion(2))
15137 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015138 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015139 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015140 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015141 if($Check eq "V")
15142 {
15143 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15144 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15145 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015146 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015148 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015149 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015150 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015151}
15152
15153sub formatVersion($$)
15154{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015155 my ($V, $Digits) = @_;
15156 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157 return join(".", splice(@Elems, 0, $Digits));
15158}
15159
15160sub htmlSpecChars($)
15161{
15162 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015163 if(not $Str) {
15164 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15167 $Str=~s/</&lt;/g;
15168 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15169 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015170 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15171 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015172 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015173 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015174 $Str=~s/\n/<br\/>/g;
15175 $Str=~s/\"/&quot;/g;
15176 $Str=~s/\'/&#39;/g;
15177 return $Str;
15178}
15179
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015180sub xmlSpecChars($)
15181{
15182 my $Str = $_[0];
15183 if(not $Str) {
15184 return $Str;
15185 }
15186
15187 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15188 $Str=~s/</&lt;/g;
15189 $Str=~s/>/&gt;/g;
15190
15191 $Str=~s/\"/&quot;/g;
15192 $Str=~s/\'/&#39;/g;
15193
15194 return $Str;
15195}
15196
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015197sub xmlSpecChars_R($)
15198{
15199 my $Str = $_[0];
15200 if(not $Str) {
15201 return $Str;
15202 }
15203
15204 $Str=~s/&amp;/&/g;
15205 $Str=~s/&lt;/</g;
15206 $Str=~s/&gt;/>/g;
15207
15208 $Str=~s/&quot;/"/g;
15209 $Str=~s/&#39;/'/g;
15210
15211 return $Str;
15212}
15213
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015214sub black_name($)
15215{
15216 my $Name = $_[0];
15217 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15218}
15219
15220sub highLight_Signature($)
15221{
15222 my $Signature = $_[0];
15223 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15224}
15225
15226sub highLight_Signature_Italic_Color($)
15227{
15228 my $Signature = $_[0];
15229 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15230}
15231
15232sub separate_symbol($)
15233{
15234 my $Symbol = $_[0];
15235 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15236 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15237 ($Name, $Spec, $Ver) = ($1, $2, $3);
15238 }
15239 return ($Name, $Spec, $Ver);
15240}
15241
15242sub cut_f_attrs($)
15243{
15244 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15245 return $2;
15246 }
15247 return "";
15248}
15249
15250sub highLight_Signature_PPos_Italic($$$$$)
15251{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015252 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15253 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015254 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15255 my $Return = "";
15256 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15257 $Return = $2;
15258 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015259 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015260 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015261 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015262 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015263 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015264 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015266 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015267 }
15268 return $Signature;
15269 }
15270 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15271 $Begin.=" " if($Begin!~/ \Z/);
15272 $End = cut_f_attrs($Signature);
15273 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015274 my ($Short, $Params) = split_Signature($Signature);
15275 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015276 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015277 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015278 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015279 $Part=~s/\A\s+|\s+\Z//g;
15280 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15281 if($Part=~/\([\*]+(\w+)\)/i) {
15282 $ParamName = $1;#func-ptr
15283 }
15284 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15285 $ParamName = $1;
15286 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015287 if(not $ParamName)
15288 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015289 push(@Parts, $Part_Styled);
15290 next;
15291 }
15292 if($ItalicParams and not $TName_Tid{1}{$Part}
15293 and not $TName_Tid{2}{$Part})
15294 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015295 my $Style = "<i>$ParamName</i>";
15296
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015297 if($Param_Pos ne ""
15298 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015299 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300 }
15301 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015302 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015304
15305 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 }
15307 $Part_Styled=~s/,(\w)/, $1/g;
15308 push(@Parts, $Part_Styled);
15309 }
15310 if(@Parts)
15311 {
15312 foreach my $Num (0 .. $#Parts)
15313 {
15314 if($Num==$#Parts)
15315 { # add ")" to the last parameter
15316 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15317 }
15318 elsif(length($Parts[$Num])<=45) {
15319 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15320 }
15321 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015322 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015323 }
15324 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015325 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326 }
15327 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015328 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015329 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015330 $Signature=~s!\[\]![&#160;]!g;
15331 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015332 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15333 if($SymbolVersion) {
15334 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15335 }
15336 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015337}
15338
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015339sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015341 my $Signature = $_[0];
15342 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15343 {
15344 $Signature=~s/\A\Q$ShortName\E\(//g;
15345 cut_f_attrs($Signature);
15346 $Signature=~s/\)\Z//;
15347 return ($ShortName, $Signature);
15348 }
15349
15350 # error
15351 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015352}
15353
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015354sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015355{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015356 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015357 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015358 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15359 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360 foreach my $Pos (0 .. length($Params) - 1)
15361 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015362 my $S = substr($Params, $Pos, 1);
15363 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015364 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015365 }
15366 if($S eq "," and
15367 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015369 if($Comma)
15370 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015371 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015373 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015374 }
15375 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015376 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015377 }
15378 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015379 if(not $Sp)
15380 { # remove spaces
15381 foreach (@Parts)
15382 {
15383 s/\A //g;
15384 s/ \Z//g;
15385 }
15386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015387 return @Parts;
15388}
15389
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015390sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391{
15392 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015393 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015395 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15396 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015397 $Center+=length($1);
15398 }
15399 foreach my $Pos (0 .. length($Sign)-1)
15400 {
15401 my $S = substr($Sign, $Pos, 1);
15402 if($S eq $Target)
15403 {
15404 if($B{"("}==$B{")"}
15405 and $B{"<"}==$B{">"}) {
15406 return $Center;
15407 }
15408 }
15409 if(defined $B{$S}) {
15410 $B{$S}+=1;
15411 }
15412 $Center+=1;
15413 }
15414 return 0;
15415}
15416
15417sub appendFile($$)
15418{
15419 my ($Path, $Content) = @_;
15420 return if(not $Path);
15421 if(my $Dir = get_dirname($Path)) {
15422 mkpath($Dir);
15423 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015424 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015425 print FILE $Content;
15426 close(FILE);
15427}
15428
15429sub writeFile($$)
15430{
15431 my ($Path, $Content) = @_;
15432 return if(not $Path);
15433 if(my $Dir = get_dirname($Path)) {
15434 mkpath($Dir);
15435 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015436 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437 print FILE $Content;
15438 close(FILE);
15439}
15440
15441sub readFile($)
15442{
15443 my $Path = $_[0];
15444 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015445 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015446 local $/ = undef;
15447 my $Content = <FILE>;
15448 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015449 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450 $Content=~s/\r/\n/g;
15451 }
15452 return $Content;
15453}
15454
15455sub get_filename($)
15456{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015457 if(defined $Cache{"get_filename"}{$_[0]}) {
15458 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015459 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015460 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15461 return ($Cache{"get_filename"}{$_[0]}=$1);
15462 }
15463 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015464}
15465
15466sub get_dirname($)
15467{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015468 if(defined $Cache{"get_dirname"}{$_[0]}) {
15469 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015471 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15472 return ($Cache{"get_dirname"}{$_[0]}=$1);
15473 }
15474 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475}
15476
15477sub separate_path($) {
15478 return (get_dirname($_[0]), get_filename($_[0]));
15479}
15480
15481sub esc($)
15482{
15483 my $Str = $_[0];
15484 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15485 return $Str;
15486}
15487
15488sub readLineNum($$)
15489{
15490 my ($Path, $Num) = @_;
15491 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015492 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015493 foreach (1 ... $Num) {
15494 <FILE>;
15495 }
15496 my $Line = <FILE>;
15497 close(FILE);
15498 return $Line;
15499}
15500
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015501sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015502{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015503 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015504 return () if(not $Path or not -f $Path);
15505 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015506 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15507 {
15508 foreach my $AttrVal (split(/;/, $1))
15509 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510 if($AttrVal=~/(.+):(.+)/)
15511 {
15512 my ($Name, $Value) = ($1, $2);
15513 $Attributes{$Name} = $Value;
15514 }
15515 }
15516 }
15517 return \%Attributes;
15518}
15519
15520sub is_abs($) {
15521 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15522}
15523
15524sub get_abs_path($)
15525{ # abs_path() should NOT be called for absolute inputs
15526 # because it can change them
15527 my $Path = $_[0];
15528 if(not is_abs($Path)) {
15529 $Path = abs_path($Path);
15530 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015531 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532}
15533
15534sub get_OSgroup()
15535{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015536 my $N = $Config{"osname"};
15537 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015538 return "macos";
15539 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015540 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015541 return "bsd";
15542 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015543 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015544 return "beos";
15545 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015546 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015547 return "symbian";
15548 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015549 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015550 return "windows";
15551 }
15552 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015553 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554 }
15555}
15556
15557sub getGccVersion($)
15558{
15559 my $LibVersion = $_[0];
15560 if($GCC_VERSION{$LibVersion})
15561 { # dump version
15562 return $GCC_VERSION{$LibVersion};
15563 }
15564 elsif($UsedDump{$LibVersion}{"V"})
15565 { # old-version dumps
15566 return "unknown";
15567 }
15568 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15569 if(not $GccVersion) {
15570 return "unknown";
15571 }
15572 return $GccVersion;
15573}
15574
15575sub showArch($)
15576{
15577 my $Arch = $_[0];
15578 if($Arch eq "arm"
15579 or $Arch eq "mips") {
15580 return uc($Arch);
15581 }
15582 return $Arch;
15583}
15584
15585sub getArch($)
15586{
15587 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015588
15589 if($TargetArch) {
15590 return $TargetArch;
15591 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015592 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015593 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015594 return $CPU_ARCH{$LibVersion};
15595 }
15596 elsif($UsedDump{$LibVersion}{"V"})
15597 { # old-version dumps
15598 return "unknown";
15599 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015600
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015601 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015602}
15603
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015604sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015606 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015608 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015609 if(getArch(1) ne getArch(2)
15610 or getArch(1) eq "unknown"
15611 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015612 { # don't show architecture in the header
15613 $ArchInfo="";
15614 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015615 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015616 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015617 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015618 }
15619 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015620 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015621 }
15622 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015623 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015624 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015625
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015626 my $V1 = $Descriptor{1}{"Version"};
15627 my $V2 = $Descriptor{2}{"Version"};
15628
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015629 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15630 {
15631 my $M1 = $UsedDump{1}{"M"};
15632 my $M2 = $UsedDump{2}{"M"};
15633
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015634 my $M1S = $M1;
15635 my $M2S = $M2;
15636
15637 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15638 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15639
15640 if($M1S eq $M2S
15641 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015642 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015643 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15644 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015645 }
15646 else
15647 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015648 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15649 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015650 }
15651 }
15652 else
15653 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015654 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015655 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015656 }
15657
15658 $Title .= $ArchInfo;
15659
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015660 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015661 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015662 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015663 $Title = "<h1>".$Title."</h1>\n";
15664 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015665}
15666
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015667sub get_CheckedHeaders($)
15668{
15669 my $LibVersion = $_[0];
15670
15671 my @Headers = ();
15672
15673 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15674 {
15675 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015676
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015677 if(not is_target_header($File, $LibVersion)) {
15678 next;
15679 }
15680
15681 if(skipHeader($File, $LibVersion)) {
15682 next;
15683 }
15684
15685 push(@Headers, $Path);
15686 }
15687
15688 return @Headers;
15689}
15690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015691sub get_SourceInfo()
15692{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015693 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015694
15695 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015697 $CheckedHeaders = "<a name='Headers'></a>";
15698 if($OldStyle) {
15699 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15700 }
15701 else {
15702 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15703 }
15704 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015705 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 +040015706 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015707 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15708 my $Name = get_filename($Identity);
15709 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15710 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015711 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015712 $CheckedHeaders .= "</div>\n";
15713 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015715
15716 if(my @Sources = keys(%{$Registered_Sources{1}}))
15717 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015718 $CheckedSources = "<a name='Sources'></a>";
15719 if($OldStyle) {
15720 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15721 }
15722 else {
15723 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15724 }
15725 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015726 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15727 {
15728 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15729 my $Name = get_filename($Identity);
15730 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15731 $CheckedSources .= $Name.$Comment."<br/>\n";
15732 }
15733 $CheckedSources .= "</div>\n";
15734 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15735 }
15736
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015737 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015739 $CheckedLibs = "<a name='Libs'></a>";
15740 if($OldStyle) {
15741 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15742 }
15743 else {
15744 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15745 }
15746 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15747 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015748 $CheckedLibs .= $Library."<br/>\n";
15749 }
15750 $CheckedLibs .= "</div>\n";
15751 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015753
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015754 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15755}
15756
15757sub get_ObjTitle()
15758{
15759 if(defined $UsedDump{1}{"DWARF"}) {
15760 return "Objects";
15761 }
15762 else {
15763 return ucfirst($SLIB_TYPE)." Libraries";
15764 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015765}
15766
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015767sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015768{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015769 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015771
15772 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015773 {
15774 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015775 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015776 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015777 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015778 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015779 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015780 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015781
15782 if($Severity ne $TargetSeverity) {
15783 next;
15784 }
15785
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015786 if($Kinds_Target{$Kind}{$Target}) {
15787 next;
15788 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015789
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015790 $Kinds_Target{$Kind}{$Target} = 1;
15791 $Type_Problems_Count += 1;
15792 }
15793 }
15794 }
15795 return $Type_Problems_Count;
15796}
15797
15798sub get_Summary($)
15799{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015800 my $Level = $_[0];
15801 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015802 $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 +040015803 %{$RESULT{$Level}} = (
15804 "Problems"=>0,
15805 "Warnings"=>0,
15806 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015808 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015809 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015810 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015811 {
15812 if(not defined $CompatRules{$Level}{$Kind})
15813 { # unknown rule
15814 if(not $UnknownRules{$Level}{$Kind})
15815 { # only one warning
15816 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15817 $UnknownRules{$Level}{$Kind}=1;
15818 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015819 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 }
15821 }
15822 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015823 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15824 {
15825 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15826 {
15827 if(not defined $CompatRules{$Level}{$Kind})
15828 { # unknown rule
15829 if(not $UnknownRules{$Level}{$Kind})
15830 { # only one warning
15831 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15832 $UnknownRules{$Level}{$Kind}=1;
15833 }
15834 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15835 }
15836 }
15837 }
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 (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015841 {
15842 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15843 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015844 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015845 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015846 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015847 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015848 $Added += 1;
15849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015850 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015851 {
15852 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015853 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015854 }
15855 else
15856 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015857 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015858 $I_Other += 1;
15859 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015860 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015861 $I_Problems_High += 1;
15862 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015863 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015864 $I_Problems_Medium += 1;
15865 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015866 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015867 $I_Problems_Low += 1;
15868 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015869 if(($Severity ne "Low" or $StrictCompat)
15870 and $Severity ne "Safe") {
15871 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 }
15873 }
15874 }
15875 }
15876 }
15877 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015878
15879 my %MethodTypeIndex = ();
15880
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015883 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15884 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015885 {
15886 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15887 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015888 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15889 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015891 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15892 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015893
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015894 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15895 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015896 next;
15897 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015898 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15899 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15900
15901 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015902
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015903 if(($Severity ne "Low" or $StrictCompat)
15904 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015905 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015906 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015907 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015908 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015909 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015910 }
15911 }
15912 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015913 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015916 }
15917 }
15918 }
15919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015920
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015921 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15922 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15923 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15924 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015925
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015926 # changed and removed public symbols
15927 my $SCount = keys(%{$CheckedSymbols{$Level}});
15928 if($ExtendedCheck)
15929 { # don't count external_func_0 for constants
15930 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015931 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015932 if($SCount)
15933 {
15934 my %Weight = (
15935 "High" => 100,
15936 "Medium" => 50,
15937 "Low" => 25
15938 );
15939 foreach (keys(%{$TotalAffected{$Level}})) {
15940 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015941 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015942 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015943 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015944 else {
15945 $RESULT{$Level}{"Affected"} = 0;
15946 }
15947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015948 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15949 if($RESULT{$Level}{"Affected"}>=100) {
15950 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015951 }
15952
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015953 $RESULT{$Level}{"Problems"} += $Removed;
15954 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015955 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015956 if($StrictCompat) {
15957 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15958 }
15959 else {
15960 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015962
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015963 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015964 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015965 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015966 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015967 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015968 if($Severity eq "Safe")
15969 {
15970 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015971 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015972 elsif($Severity eq "Low")
15973 {
15974 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015976 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015977 }
15978
15979 if($C_Problems_Low)
15980 {
15981 if($StrictCompat) {
15982 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15983 }
15984 else {
15985 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015986 }
15987 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015988 if($RESULT{$Level}{"Problems"}
15989 and $RESULT{$Level}{"Affected"}) {
15990 $RESULT{$Level}{"Verdict"} = "incompatible";
15991 }
15992 else {
15993 $RESULT{$Level}{"Verdict"} = "compatible";
15994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995
15996 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15997 if(not $TotalTypes)
15998 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015999 $TotalTypes = keys(%{$TName_Tid{1}});
16000 }
16001
16002 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
16003 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016004 my ($ClangV1, $ClangV2) = ($CLANG_VERSION{1}, $CLANG_VERSION{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016005
16006 my ($TestInfo, $TestResults, $Problem_Summary) = ();
16007
16008 if($ReportFormat eq "xml")
16009 { # XML
16010 # test info
16011 $TestInfo .= " <library>$TargetLibraryName</library>\n";
16012 $TestInfo .= " <version1>\n";
16013 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016014 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016015 if($GccV1) {
16016 $TestInfo .= " <gcc>$GccV1</gcc>\n";
16017 }
16018 elsif($ClangV1) {
16019 $TestInfo .= " <clang>$ClangV1</clang>\n";
16020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016021 $TestInfo .= " </version1>\n";
16022
16023 $TestInfo .= " <version2>\n";
16024 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016025 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016026 if($GccV2) {
16027 $TestInfo .= " <gcc>$GccV2</gcc>\n";
16028 }
16029 elsif($ClangV2) {
16030 $TestInfo .= " <clang>$ClangV2</clang>\n";
16031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016032 $TestInfo .= " </version2>\n";
16033 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
16034
16035 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016036 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016037 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016038 $TestResults .= " <headers>\n";
16039 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
16040 {
16041 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
16042 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16043 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16044 }
16045 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016047
16048 if(my @Sources = keys(%{$Registered_Sources{1}}))
16049 {
16050 $TestResults .= " <sources>\n";
16051 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16052 {
16053 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16054 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16055 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16056 }
16057 $TestResults .= " </sources>\n";
16058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016059
16060 $TestResults .= " <libs>\n";
16061 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16062 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016063 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016064 $TestResults .= " <name>$Library</name>\n";
16065 }
16066 $TestResults .= " </libs>\n";
16067
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016068 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016069 $TestResults .= " <types>".$TotalTypes."</types>\n";
16070
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016071 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16072 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016073 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16074
16075 # problem summary
16076 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16077 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16078
16079 $Problem_Summary .= " <problems_with_types>\n";
16080 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16081 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16082 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16083 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16084 $Problem_Summary .= " </problems_with_types>\n";
16085
16086 $Problem_Summary .= " <problems_with_symbols>\n";
16087 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16088 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16089 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016090 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016091 $Problem_Summary .= " </problems_with_symbols>\n";
16092
16093 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016094 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016095 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016096
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016097 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16098
16099 return ($TestInfo.$TestResults.$Problem_Summary, "");
16100 }
16101 else
16102 { # HTML
16103 # test info
16104 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016105 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016106
16107 if($TargetComponent eq "library") {
16108 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16109 }
16110 else {
16111 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016113
16114 my (@VInf1, @VInf2, $AddTestInfo) = ();
16115 if($Arch1 ne "unknown"
16116 and $Arch2 ne "unknown")
16117 { # CPU arch
16118 if($Arch1 eq $Arch2)
16119 { # go to the separate section
Andrey Ponomarenko19b61de2016-08-31 19:45:06 +030016120 $AddTestInfo .= "<tr><th>Arch</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016121 }
16122 else
16123 { # go to the version number
16124 push(@VInf1, showArch($Arch1));
16125 push(@VInf2, showArch($Arch2));
16126 }
16127 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016128 if($Level eq "Binary"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016129 and $OStarget ne "windows")
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016130 {
16131 if($GccV1 ne "unknown"
16132 and $GccV2 ne "unknown")
16133 { # GCC version
16134 if($GccV1 eq $GccV2)
16135 { # go to the separate section
16136 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16137 }
16138 else
16139 { # go to the version number
16140 push(@VInf1, "gcc ".$GccV1);
16141 push(@VInf2, "gcc ".$GccV2);
16142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016144 elsif($ClangV1
16145 and $ClangV2)
16146 { # Clang version
16147 if($ClangV1 eq $ClangV2)
16148 { # go to the separate section
16149 $AddTestInfo .= "<tr><th>Clang Version</th><td>$ClangV1</td></tr>\n";
16150 }
16151 else
16152 { # go to the version number
16153 push(@VInf1, "clang ".$ClangV1);
16154 push(@VInf2, "clang ".$ClangV2);
16155 }
16156 }
16157 elsif($GccV1 ne "unknown" and $ClangV2)
16158 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016159 push(@VInf1, "gcc ".$GccV1);
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030016160 push(@VInf2, "clang ".$ClangV2);
16161 }
16162 elsif($ClangV1 and $GccV2 ne "unknown")
16163 {
16164 push(@VInf1, "clang ".$ClangV1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016165 push(@VInf2, "gcc ".$GccV2);
16166 }
16167 }
16168 # show long version names with GCC version and CPU architecture name (if different)
16169 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16170 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16171 $TestInfo .= $AddTestInfo;
16172 #if($COMMON_LANGUAGE{1}) {
16173 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16174 #}
16175 if($ExtendedCheck) {
16176 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16177 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016178 if($JoinReport)
16179 {
16180 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016181 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016182 }
16183 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016184 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016185 }
16186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187 $TestInfo .= "</table>\n";
16188
16189 # test results
16190 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016191 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016193 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016194 {
16195 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16196 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16197 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016198
16199 if(my @Sources = keys(%{$Registered_Sources{1}}))
16200 {
16201 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16202 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204
16205 if(not $ExtendedCheck)
16206 {
16207 my $Libs_Link = "0";
16208 $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 +040016209 $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 +040016210 }
16211
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016212 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016213
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016214 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 if($JoinReport) {
16216 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16217 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016218
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016219 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016220
16221 $TestResults .= "<tr><th>Compatibility</th>\n";
16222 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16223 {
16224 my $Cl = "incompatible";
16225 if($BC_Rate>=90) {
16226 $Cl = "warning";
16227 }
16228 elsif($BC_Rate>=80) {
16229 $Cl = "almost_compatible";
16230 }
16231
16232 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016233 }
16234 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016235 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016236 }
16237 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016238 $TestResults .= "</table>\n";
16239
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016240 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016241 # problem summary
16242 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016243 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016244 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16245
16246 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 if($Added>0)
16248 {
16249 if($JoinReport) {
16250 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16251 }
16252 else {
16253 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16254 }
16255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016257 $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 +040016258
16259 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 if($Removed>0)
16261 {
16262 if($JoinReport) {
16263 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16264 }
16265 else {
16266 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16267 }
16268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016270 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016271 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272
16273 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016274 $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 +040016275 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016276 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016277 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016278
16279 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016280 $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 +040016281 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016282 $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 +040016283
16284 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016285 $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 +040016286 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016287 $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 +040016288
16289 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016290 $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 +040016291 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016292 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016293 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016294
16295 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016296 $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 +040016297 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016298 $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 +040016299
16300 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016301 $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 +040016302 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016303 $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 +040016304
16305 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016306 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16307 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016309 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016310 $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 +040016311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016313 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016314 {
16315 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016316 $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 +030016317 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016319
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016320 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016321 {
16322 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016323 $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 +030016324 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016326
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016327 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016328 {
16329 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016330 $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 +030016331 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016332 }
16333
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016334 $META_DATA .= "tool_version:$TOOL_VERSION";
16335 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016336
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016337 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16338 }
16339}
16340
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016341sub getStyle($$$)
16342{
16343 my ($Subj, $Act, $Num) = @_;
16344 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016345 "Added"=>"new",
16346 "Removed"=>"failed",
16347 "Safe"=>"passed",
16348 "Low"=>"warning",
16349 "Medium"=>"failed",
16350 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016351 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016352
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016353 if($Num>0) {
16354 return " class='".$Style{$Act}."'";
16355 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016356
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016357 return "";
16358}
16359
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016360sub show_number($)
16361{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016362 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016363 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016364 my $Num = cut_off_number($_[0], 2, 0);
16365 if($Num eq "0")
16366 {
16367 foreach my $P (3 .. 7)
16368 {
16369 $Num = cut_off_number($_[0], $P, 1);
16370 if($Num ne "0") {
16371 last;
16372 }
16373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 }
16375 if($Num eq "0") {
16376 $Num = $_[0];
16377 }
16378 return $Num;
16379 }
16380 return $_[0];
16381}
16382
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016383sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016384{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016385 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016386 if($num!~/\./)
16387 {
16388 $num .= ".";
16389 foreach (1 .. $digs_to_cut-1) {
16390 $num .= "0";
16391 }
16392 }
16393 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16394 {
16395 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16396 $num .= "0";
16397 }
16398 }
16399 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16400 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16401 }
16402 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016403 if($z) {
16404 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406 return $num;
16407}
16408
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016409sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016410{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016411 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016412 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016413
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016414 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016415 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16416 {
16417 my $Header = $Constants{1}{$Constant}{"Header"};
16418 if(not $Header)
16419 { # added
16420 $Header = $Constants{2}{$Constant}{"Header"}
16421 }
16422
16423 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16424 {
16425 if(not defined $CompatRules{$Level}{$Kind}) {
16426 next;
16427 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016428 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016429 next;
16430 }
16431 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016433 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 if($ReportFormat eq "xml")
16436 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016437 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016438 {
16439 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016440 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 {
16442 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016443 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16444 {
16445 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16446 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16447 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016448
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016449 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16450 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16451 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016452 if($Overcome) {
16453 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16454 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016455 $CHANGED_CONSTANTS .= " </problem>\n";
16456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016457 $CHANGED_CONSTANTS .= " </constant>\n";
16458 }
16459 $CHANGED_CONSTANTS .= " </header>\n";
16460 }
16461 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16462 }
16463 else
16464 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016465 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016466 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 {
16468 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016469 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016470 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016471 my $Report = "";
16472
16473 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16474 {
16475 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16476 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016477 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016478 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016479 }
16480 if($Report)
16481 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016482 $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 +030016483 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016484 $Report = insertIDs($Report);
16485 }
16486 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 }
16488 $CHANGED_CONSTANTS .= "<br/>\n";
16489 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016490 if($CHANGED_CONSTANTS)
16491 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016492 my $Title = "Problems with Constants, $TargetSeverity Severity";
16493 if($TargetSeverity eq "Safe")
16494 { # Safe Changes
16495 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016496 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016497 if($OldStyle) {
16498 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16499 }
16500 else {
16501 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16502 }
16503 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
16505 }
16506 return $CHANGED_CONSTANTS;
16507}
16508
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509sub getTitle($$$)
16510{
16511 my ($Header, $Library, $NameSpace) = @_;
16512 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016513
16514 # if($Library and $Library!~/\.\w+\Z/) {
16515 # $Library .= " (.$LIB_EXT)";
16516 # }
16517
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016518 if($Header and $Library)
16519 {
16520 $Title .= "<span class='h_name'>$Header</span>";
16521 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16522 }
16523 elsif($Library) {
16524 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16525 }
16526 elsif($Header) {
16527 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16528 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016529
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016530 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016531 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016532 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016533
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016534 return $Title;
16535}
16536
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016537sub get_Report_Added($)
16538{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016540 my $ADDED_INTERFACES = "";
16541 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016542 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016543 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016544 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016545 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016546 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016547 {
16548 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16549 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016550 if($Level eq "Source" and $ReportFormat eq "html")
16551 { # do not show library name in HTML report
16552 $DyLib = "";
16553 }
16554 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016555 }
16556 }
16557 }
16558 if($ReportFormat eq "xml")
16559 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016560 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016561 {
16562 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 {
16565 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016566 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016567 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16568 }
16569 $ADDED_INTERFACES .= " </library>\n";
16570 }
16571 $ADDED_INTERFACES .= " </header>\n";
16572 }
16573 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16574 }
16575 else
16576 { # HTML
16577 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016578 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 my %NameSpaceSymbols = ();
16583 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016584 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016585 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016586 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016588 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16589 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 foreach my $Interface (@SortedInterfaces)
16591 {
16592 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016593 my $Signature = get_Signature($Interface, 2);
16594 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016595 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016597 if($Interface=~/\A(_Z|\?)/)
16598 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016599 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016600 $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 +040016601 }
16602 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016603 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 }
16605 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016606 else
16607 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016608 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 }
16611 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016612 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016613 }
16614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016616 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 }
16619 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016620 if($ADDED_INTERFACES)
16621 {
16622 my $Anchor = "<a name='Added'></a>";
16623 if($JoinReport) {
16624 $Anchor = "<a name='".$Level."_Added'></a>";
16625 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016626 if($OldStyle) {
16627 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16628 }
16629 else {
16630 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16631 }
16632 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016633 }
16634 }
16635 return $ADDED_INTERFACES;
16636}
16637
16638sub get_Report_Removed($)
16639{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016641 my $REMOVED_INTERFACES = "";
16642 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016643 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016645 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016649 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16650 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016651 if($Level eq "Source" and $ReportFormat eq "html")
16652 { # do not show library name in HTML report
16653 $DyLib = "";
16654 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016655 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016656 }
16657 }
16658 }
16659 if($ReportFormat eq "xml")
16660 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016661 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016662 {
16663 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016664 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 {
16666 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016667 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16668 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016669 }
16670 $REMOVED_INTERFACES .= " </library>\n";
16671 }
16672 $REMOVED_INTERFACES .= " </header>\n";
16673 }
16674 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16675 }
16676 else
16677 { # HTML
16678 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016679 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016683 my %NameSpaceSymbols = ();
16684 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016685 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016687 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016689 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16690 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016691 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 {
16693 $Removed_Number += 1;
16694 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016695 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016696 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016697 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016699 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016701 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016702 $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 +040016703 }
16704 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016705 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016706 }
16707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016708 else
16709 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016711 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016712 }
16713 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016714 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016715 }
16716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016717 }
16718 }
16719 $REMOVED_INTERFACES .= "<br/>\n";
16720 }
16721 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 if($REMOVED_INTERFACES)
16723 {
16724 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16725 if($JoinReport) {
16726 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16727 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016728 if($OldStyle) {
16729 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16730 }
16731 else {
16732 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16733 }
16734
16735 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 }
16737 }
16738 return $REMOVED_INTERFACES;
16739}
16740
16741sub getXmlParams($$)
16742{
16743 my ($Content, $Problem) = @_;
16744 return "" if(not $Content or not $Problem);
16745 my %XMLparams = ();
16746 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16747 {
16748 my $Macro = "\@".lc($Attr);
16749 if($Content=~/\Q$Macro\E/) {
16750 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16751 }
16752 }
16753 my @PString = ();
16754 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016755 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 }
16757 if(@PString) {
16758 return " ".join(" ", @PString);
16759 }
16760 else {
16761 return "";
16762 }
16763}
16764
16765sub addMarkup($)
16766{
16767 my $Content = $_[0];
16768 # auto-markup
16769 $Content=~s/\n[ ]*//; # spaces
16770 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16771 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016772 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016773 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16774 if($Content=~/\ANOTE:/)
16775 { # notes
16776 $Content=~s!(NOTE):!<b>$1</b>:!g;
16777 }
16778 else {
16779 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16780 }
16781 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16782 my @Keywords = (
16783 "void",
16784 "const",
16785 "static",
16786 "restrict",
16787 "volatile",
16788 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016789 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016790 );
16791 my $MKeys = join("|", @Keywords);
16792 foreach (@Keywords) {
16793 $MKeys .= "|non-".$_;
16794 }
16795 $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 +040016796
16797 # Markdown
16798 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16799 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016800 return $Content;
16801}
16802
16803sub applyMacroses($$$$)
16804{
16805 my ($Level, $Kind, $Content, $Problem) = @_;
16806 return "" if(not $Content or not $Problem);
16807 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16808 $Content = addMarkup($Content);
16809 # macros
16810 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16811 {
16812 my $Macro = "\@".lc($Attr);
16813 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016814 if(not defined $Value
16815 or $Value eq "") {
16816 next;
16817 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016818
16819 if(index($Content, $Macro)==-1) {
16820 next;
16821 }
16822
16823 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16824 and $Kind!~/_Type_/
16825 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016828 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016829 $Value = black_name($Value);
16830 }
16831 elsif($Value=~/\s/) {
16832 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16833 }
16834 elsif($Value=~/\A\d+\Z/
16835 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16836 { # bits to bytes
16837 if($Value % $BYTE_SIZE)
16838 { # bits
16839 if($Value==1) {
16840 $Value = "<b>".$Value."</b> bit";
16841 }
16842 else {
16843 $Value = "<b>".$Value."</b> bits";
16844 }
16845 }
16846 else
16847 { # bytes
16848 $Value /= $BYTE_SIZE;
16849 if($Value==1) {
16850 $Value = "<b>".$Value."</b> byte";
16851 }
16852 else {
16853 $Value = "<b>".$Value."</b> bytes";
16854 }
16855 }
16856 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016857 else
16858 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016859 $Value = "<b>".htmlSpecChars($Value)."</b>";
16860 }
16861 $Content=~s/\Q$Macro\E/$Value/g;
16862 }
16863
16864 if($Content=~/(\A|[^\@\w])\@\w/)
16865 {
16866 if(not $IncompleteRules{$Level}{$Kind})
16867 { # only one warning
16868 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16869 $IncompleteRules{$Level}{$Kind} = 1;
16870 }
16871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 return $Content;
16873}
16874
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016875sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016876{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016877 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016878 my $INTERFACE_PROBLEMS = "";
16879 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016880
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16884 if($SV and defined $CompatProblems{$Level}{$SN}) {
16885 next;
16886 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016887 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16888 my $DyLib = $Symbol_Library{1}{$Symbol};
16889 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16890 { # Symbol with Version
16891 $DyLib = $Symbol_Library{1}{$VSym};
16892 }
16893 if(not $DyLib)
16894 { # const global data
16895 $DyLib = "";
16896 }
16897 if($Level eq "Source" and $ReportFormat eq "html")
16898 { # do not show library name in HTML report
16899 $DyLib = "";
16900 }
16901
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016902 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 {
16904 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016906 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016907 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16908 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016909 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016910 if($Severity eq $TargetSeverity)
16911 {
16912 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16913 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016914 }
16915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016916 }
16917 }
16918 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016919
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 if($ReportFormat eq "xml")
16921 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016922 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016923 {
16924 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016925 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 {
16927 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016928 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16929 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016930 {
16931 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016932 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016933 {
16934 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16935 {
16936 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016937 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016938
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016939 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16940 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16941 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16942 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16943 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016944 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16945 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 $INTERFACE_PROBLEMS .= " </problem>\n";
16948 }
16949 }
16950 $INTERFACE_PROBLEMS .= " </symbol>\n";
16951 }
16952 $INTERFACE_PROBLEMS .= " </library>\n";
16953 }
16954 $INTERFACE_PROBLEMS .= " </header>\n";
16955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016956 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957 }
16958 else
16959 { # HTML
16960 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016961 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016963 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016965 my (%NameSpaceSymbols, %NewSignature) = ();
16966 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016967 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016970 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016971 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016972 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 +040016973 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016975 my $Signature = get_Signature($Symbol, 1);
16976 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016978 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016983 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016984 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016985 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016986 }
16987 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16988 {
16989 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016990 $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 +040016991 $ProblemNum += 1;
16992 $ProblemsNum += 1;
16993 }
16994 }
16995 }
16996 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016997 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016998 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016999 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017001 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017003
17004 if($NameSpace)
17005 {
17006 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
17007 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017009
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017010 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
17011 if($OldStyle) {
17012 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
17013 }
17014 else {
17015 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17016 }
17017 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017018 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017019
17020 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017021 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017022 if($NameSpace) {
17023 $NSign = cut_Namespace($NSign, $NameSpace);
17024 }
17025 $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 +040017026 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017027
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017028 if($Symbol=~/\A(_Z|\?)/) {
17029 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
17030 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017031
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017032 $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 +040017033 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017034 }
17035 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017036 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017037 }
17038 }
17039 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017041 if($INTERFACE_PROBLEMS)
17042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017043 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
17044 my $Title = "Problems with Symbols, $TargetSeverity Severity";
17045 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017046 { # Safe Changes
17047 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017048 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017049 if($OldStyle) {
17050 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
17051 }
17052 else {
17053 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
17054 }
17055 $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 +040017056 }
17057 }
17058 return $INTERFACE_PROBLEMS;
17059}
17060
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017061sub cut_Namespace($$)
17062{
17063 my ($N, $Ns) = @_;
17064 $N=~s/\b\Q$Ns\E:://g;
17065 return $N;
17066}
17067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017068sub get_Report_TypeProblems($$)
17069{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017070 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017071 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017072
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017073 my %ReportMap = ();
17074 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017075
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017076 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017078 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17079
17080 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017082 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017083 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017084 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017085 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017086
17087 if($Severity eq $TargetSeverity)
17088 {
17089 $ReportMap{$HeaderName}{$TypeName} = 1;
17090 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017095
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017096 if($ReportFormat eq "xml")
17097 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017098 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017099 {
17100 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017101 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017103 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017104 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017105 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017107 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017109 $Kinds_Locations{$Kind}{$Location} = 1;
17110
17111 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17112 if($Kinds_Target{$Kind}{$Target}) {
17113 next;
17114 }
17115 $Kinds_Target{$Kind}{$Target} = 1;
17116
17117 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017118 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17119 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17120 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17121 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17122 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017123 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17124 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 $TYPE_PROBLEMS .= " </problem>\n";
17127 }
17128 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017129 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17130 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 $TYPE_PROBLEMS .= showVTables($TypeName);
17132 }
17133 $TYPE_PROBLEMS .= " </type>\n";
17134 }
17135 $TYPE_PROBLEMS .= " </header>\n";
17136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017137 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 }
17139 else
17140 { # HTML
17141 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017142 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017144 my (%NameSpace_Type) = ();
17145 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017146 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017147 }
17148 foreach my $NameSpace (sort keys(%NameSpace_Type))
17149 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017150 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017151 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 +040017152 foreach my $TypeName (@SortedTypes)
17153 {
17154 my $ProblemNum = 1;
17155 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017156 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017157
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017158 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017159 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017160 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017161 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017162 $Kinds_Locations{$Kind}{$Location} = 1;
17163
17164 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17165 if($Kinds_Target{$Kind}{$Target}) {
17166 next;
17167 }
17168 $Kinds_Target{$Kind}{$Target} = 1;
17169
17170 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017171 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17172 {
17173 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017174 $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 +040017175 $ProblemNum += 1;
17176 $ProblemsNum += 1;
17177 }
17178 }
17179 }
17180 $ProblemNum -= 1;
17181 if($TYPE_REPORT)
17182 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017183 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017184 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017185 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017186 $ShowVTables = showVTables($TypeName);
17187 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017188
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017189 my $ShowType = show_Type($TypeName, 1, 1);
17190
17191 if($NameSpace)
17192 {
17193 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17194 $ShowType = cut_Namespace($ShowType, $NameSpace);
17195 $Affected = cut_Namespace($Affected, $NameSpace);
17196 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17197 }
17198
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017199 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17200 if($OldStyle) {
17201 $TYPE_PROBLEMS .= " ($ProblemNum)";
17202 }
17203 else {
17204 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17205 }
17206 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017207 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17208 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17209 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17210 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 }
17212 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017213 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017214 }
17215 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017216
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017217 if($TYPE_PROBLEMS)
17218 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017219 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17220 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017221 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 { # Safe Changes
17223 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017224 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017225 if($OldStyle) {
17226 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17227 }
17228 else {
17229 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17230 }
17231 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232 }
17233 }
17234 return $TYPE_PROBLEMS;
17235}
17236
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017237sub show_Type($$$)
17238{
17239 my ($Name, $Html, $LibVersion) = @_;
17240 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17241 $TType = lc($TType);
17242 if($TType=~/struct|union|enum/) {
17243 $Name=~s/\A\Q$TType\E //g;
17244 }
17245 if($Html) {
17246 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17247 }
17248 else {
17249 $Name = $TType." ".$Name;
17250 }
17251 return $Name;
17252}
17253
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017254sub get_Anchor($$$)
17255{
17256 my ($Kind, $Level, $Severity) = @_;
17257 if($JoinReport)
17258 {
17259 if($Severity eq "Safe") {
17260 return "Other_".$Level."_Changes_In_".$Kind."s";
17261 }
17262 else {
17263 return $Kind."_".$Level."_Problems_".$Severity;
17264 }
17265 }
17266 else
17267 {
17268 if($Severity eq "Safe") {
17269 return "Other_Changes_In_".$Kind."s";
17270 }
17271 else {
17272 return $Kind."_Problems_".$Severity;
17273 }
17274 }
17275}
17276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277sub showVTables($)
17278{
17279 my $TypeName = $_[0];
17280 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017281 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017282 if(defined $Type1{"VTable"}
17283 and keys(%{$Type1{"VTable"}}))
17284 {
17285 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017286 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017287 if(defined $Type2{"VTable"}
17288 and keys(%{$Type2{"VTable"}}))
17289 {
17290 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17291 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017292 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017294 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17295 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 }
17297 my $VTABLES = "";
17298 if($ReportFormat eq "xml")
17299 { # XML
17300 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017301 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017302 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017303 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017304 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17305 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017306 $VTABLES .= " </entry>\n";
17307 }
17308 $VTABLES .= " </vtable>\n\n";
17309 }
17310 else
17311 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017312 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017313 $VTABLES .= "<tr><th>Offset</th>";
17314 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017315 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017316 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 {
17318 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017319
17320 my $E1 = $Entries{$Index}{"E1"};
17321 my $E2 = $Entries{$Index}{"E2"};
17322
17323 if($E1 ne $E2
17324 and $E1!~/ 0x/
17325 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017327 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017329 $Color1 = " class='failed'";
17330 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017331 }
17332 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017333 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334 }
17335 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017336 $VTABLES .= "<tr><th>".$Index."</th>\n";
17337 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17338 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 }
17340 $VTABLES .= "</table><br/>\n";
17341 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017342 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017343 }
17344 return $VTABLES;
17345 }
17346 }
17347 return "";
17348}
17349
17350sub simpleVEntry($)
17351{
17352 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017353 if(not defined $VEntry
17354 or $VEntry eq "") {
17355 return "";
17356 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017357
17358 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17360 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17361 if($VEntry=~/\A_ZThn.+\Z/) {
17362 $VEntry = "non-virtual thunk";
17363 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017364 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017365 # support for old GCC versions
17366 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17367 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17368 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17370 return $VEntry;
17371}
17372
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017373sub adjustParamPos($$$)
17374{
17375 my ($Pos, $Symbol, $LibVersion) = @_;
17376 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17377 {
17378 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17379 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17380 {
17381 return $Pos-1;
17382 }
17383
17384 return $Pos;
17385 }
17386
17387 return undef;
17388}
17389
17390sub getParamPos($$$)
17391{
17392 my ($Name, $Symbol, $LibVersion) = @_;
17393
17394 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17395 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17396 {
17397 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17398 foreach (keys(%{$Info->{"Param"}}))
17399 {
17400 if($Info->{"Param"}{$_}{"name"} eq $Name)
17401 {
17402 return $_;
17403 }
17404 }
17405 }
17406
17407 return undef;
17408}
17409
17410sub getParamName($)
17411{
17412 my $Loc = $_[0];
17413 $Loc=~s/\->.*//g;
17414 return $Loc;
17415}
17416
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017417sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017418{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017419 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017420
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017421 my $LIMIT = 10;
17422 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017423 $LIMIT = $AffectLimit;
17424 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017425
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017426 my @Kinds = sort keys(%{$Kinds_Locations});
17427 my %KLocs = ();
17428 foreach my $Kind (@Kinds)
17429 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017430 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 +030017431 $KLocs{$Kind} = \@Locs;
17432 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017433
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017434 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017435 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017436 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017437 if(index($Symbol, "_Z")==0
17438 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017439 { # duplicated problems for C2 constructors, D2 and D0 destructors
17440 next;
17441 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017442
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017443 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017444 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017445 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017446 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017447 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448 next;
17449 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017450
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017451 if(index($Symbol, "\@")!=-1
17452 or index($Symbol, "\$")!=-1)
17453 {
17454 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17455
17456 if($Level eq "Source")
17457 { # remove symbol version
17458 $Symbol = $SN;
17459 }
17460
17461 if($SV and defined $CompatProblems{$Level}{$SN}
17462 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17463 { # duplicated problems for versioned symbols
17464 next;
17465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017466 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017467
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017468 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017469 if($Type_Name ne $Target_TypeName) {
17470 next;
17471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017472
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017473 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017474 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017475 }
17476 }
17477 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017478
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017479 %KLocs = (); # clear
17480
17481 my %SymSel = ();
17482 my $Num = 0;
17483 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017484 {
17485 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17486 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017487 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017488 {
17489 $SymSel{$Symbol}{"Loc"} = $Loc;
17490 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017491 last LOOP;
17492 }
17493 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017494
17495 $Num += 1;
17496
17497 if($Num>=$LIMIT) {
17498 last;
17499 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017500 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017501
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017502 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017503
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 if($ReportFormat eq "xml")
17505 { # XML
17506 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017507
17508 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017509 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017510 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017511 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017512
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017513 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017514 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017515
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017516 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017517 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017518 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017519 $Target .= " param=\"$PName\"";
17520 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017521 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017522 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017523 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017524 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017525 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017526 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017527 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017528
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017529 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017530 $Target .= " field=\"$1\"";
17531 }
17532
17533 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017534 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017535 $Affected .= " </symbol>\n";
17536 }
17537 $Affected .= " </affected>\n";
17538 }
17539 else
17540 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017541 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017542 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017543 my $Kind = $SymSel{$Symbol}{"Kind"};
17544 my $Loc = $SymSel{$Symbol}{"Loc"};
17545
17546 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017547 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017548 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017549 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17550
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017551 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017552 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017553 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017554
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017555 if(keys(%SymLocKind)>$LIMIT) {
17556 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017557 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017558
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017559 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017560 if($Affected)
17561 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017562 my $Num = keys(%SymLocKind);
17563 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017564 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017565 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017566 }
17567 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017569 return $Affected;
17570}
17571
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017572sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017574 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017575 if($L2=~/\A(retval|this)\b/
17576 and $L1!~/\A(retval|this)\b/)
17577 {
17578 if($L1!~/\-\>/) {
17579 return 1;
17580 }
17581 elsif($L2=~/\-\>/) {
17582 return 1;
17583 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584 }
17585 return 0;
17586}
17587
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017588sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017589{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017590 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017591
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017592 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017593
17594 my $Location_I = $Location;
17595 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017597 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017599 if($Kind eq "Overridden_Virtual_Method"
17600 or $Kind eq "Overridden_Virtual_Method_B") {
17601 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17602 }
17603 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17604 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017605 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017607 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17608 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017609 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17610 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17611
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017612 if($ClassName eq $Problem{"Type_Name"}) {
17613 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17614 }
17615 else {
17616 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17617 }
17618 }
17619 else
17620 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017621 my $TypeID = undef;
17622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017623 if($Location=~/retval/)
17624 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017625 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017626 push(@Sentence, "Field \'".$Location."\' in return value");
17627 }
17628 else {
17629 push(@Sentence, "Return value");
17630 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017631
17632 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017633 }
17634 elsif($Location=~/this/)
17635 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017636 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017637 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17638 }
17639 else {
17640 push(@Sentence, "\'this\' pointer");
17641 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017642
17643 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017644 }
17645 else
17646 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017647
17648 my $PName = getParamName($Location);
17649 my $PPos = getParamPos($PName, $Symbol, 1);
17650
17651 if(index($Location, "->")!=-1) {
17652 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017653 }
17654 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017655 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017657 if($PName) {
17658 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017659 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017660
17661 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17662 }
17663
17664 if($Location!~/this/)
17665 {
17666 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017667 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017668 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017669 push(@Sentence, "(pointer)");
17670 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017671 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017672 push(@Sentence, "(reference)");
17673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017674 }
17675 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017676
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017677 if($Location eq "this") {
17678 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17679 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017680 else
17681 {
17682 my $Location_T = $Location;
17683 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17684
17685 my $TypeID_Problem = $TypeID;
17686 if($Location_T) {
17687 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17688 }
17689
17690 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17691 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17692 }
17693 else {
17694 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017696 }
17697 }
17698 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017699 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017700 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 +040017701 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017702
17703 my $Sent = join(" ", @Sentence);
17704
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017705 $Sent=~s/->/./g;
17706
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017707 if($ReportFormat eq "xml")
17708 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017709 $Sent=~s/'//g;
17710 }
17711
17712 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017713}
17714
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017715sub getFieldType($$$)
17716{
17717 my ($Location, $TypeId, $LibVersion) = @_;
17718
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017719 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017720
17721 foreach my $Name (@Fields)
17722 {
17723 my %Info = get_BaseType($TypeId, $LibVersion);
17724
17725 foreach my $Pos (keys(%{$Info{"Memb"}}))
17726 {
17727 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17728 {
17729 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17730 last;
17731 }
17732 }
17733 }
17734
17735 return $TypeId;
17736}
17737
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017738sub get_XmlSign($$)
17739{
17740 my ($Symbol, $LibVersion) = @_;
17741 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17742 my $Report = "";
17743 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17744 {
17745 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017746 my $Type = $Info->{"Param"}{$Pos}{"type"};
17747 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017748 foreach my $Typedef (keys(%ChangedTypedef))
17749 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017750 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17751 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017753 }
17754 $Report .= " <param pos=\"$Pos\">\n";
17755 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017756 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017757 $Report .= " </param>\n";
17758 }
17759 if(my $Return = $Info->{"Return"})
17760 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017761 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017762 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017763 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017764 $Report .= " </retval>\n";
17765 }
17766 return $Report;
17767}
17768
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017769sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017770{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017771 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017772 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017773 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017774 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017775 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17776 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017777 next;
17778 }
17779 $Report .= " <symbol name=\"$Symbol\">\n";
17780 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017781 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017782 {
17783 if(defined $CompleteSignature{1}{$Symbol}
17784 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17785 {
17786 $P1 = get_XmlSign($Symbol, 1);
17787 $S1 = get_Signature($Symbol, 1);
17788 }
17789 elsif($Symbol=~/\A(_Z|\?)/) {
17790 $S1 = $tr_name{$Symbol};
17791 }
17792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017793 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794 {
17795 if(defined $CompleteSignature{2}{$Symbol}
17796 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17797 {
17798 $P2 = get_XmlSign($Symbol, 2);
17799 $S2 = get_Signature($Symbol, 2);
17800 }
17801 elsif($Symbol=~/\A(_Z|\?)/) {
17802 $S2 = $tr_name{$Symbol};
17803 }
17804 }
17805 if($S1)
17806 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017807 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808 $Report .= $P1;
17809 $Report .= " </old>\n";
17810 }
17811 if($S2 and $S2 ne $S1)
17812 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017813 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017814 $Report .= $P2;
17815 $Report .= " </new>\n";
17816 }
17817 $Report .= " </symbol>\n";
17818 }
17819 $Report .= "</symbols_info>\n";
17820 return $Report;
17821}
17822
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017823sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017824{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017825 my ($Level, $Report) = @_;
17826 if($ReportFormat eq "xml") {
17827 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017828 }
17829 if($StdOut)
17830 { # --stdout option
17831 print STDOUT $Report;
17832 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017833 else
17834 {
17835 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017836 mkpath(get_dirname($RPath));
17837
17838 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17839 print REPORT $Report;
17840 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017841 }
17842}
17843
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017844sub getReport($)
17845{
17846 my $Level = $_[0];
17847 if($ReportFormat eq "xml")
17848 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017849 if($Level eq "Join")
17850 {
17851 my $Report = "<reports>\n";
17852 $Report .= getReport("Binary");
17853 $Report .= getReport("Source");
17854 $Report .= "</reports>\n";
17855 return $Report;
17856 }
17857 else
17858 {
17859 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17860 my ($Summary, $MetaData) = get_Summary($Level);
17861 $Report .= $Summary."\n";
17862 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17863 $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 +040017864
17865 # additional symbols info (if needed)
17866 # $Report .= get_Report_SymbolsInfo($Level);
17867
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017868 $Report .= "</report>\n";
17869 return $Report;
17870 }
17871 }
17872 else
17873 { # HTML
17874 my $CssStyles = readModule("Styles", "Report.css");
17875 my $JScripts = readModule("Scripts", "Sections.js");
17876 if($Level eq "Join")
17877 {
17878 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17879 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017880 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017881 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17882 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 +040017883 my ($BSummary, $BMetaData) = get_Summary("Binary");
17884 my ($SSummary, $SMetaData) = get_Summary("Source");
17885 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 +030017886 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017887 <br/>
17888 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017889 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17890 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017891 </div>";
17892 $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>";
17893 $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 +030017894 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017895 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017896 return $Report;
17897 }
17898 else
17899 {
17900 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017901 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17902 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17903 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 +040017904 if($Level eq "Binary")
17905 {
17906 if(getArch(1) eq getArch(2)
17907 and getArch(1) ne "unknown") {
17908 $Description .= " on ".showArch(getArch(1));
17909 }
17910 }
17911 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 +030017912 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017913 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17914 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17915 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017916 $Report .= "</div>\n<br/><br/><br/>\n";
17917 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017918 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017919 return $Report;
17920 }
17921 }
17922}
17923
17924sub createReport()
17925{
17926 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017927 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017928 writeReport("Join", getReport("Join"));
17929 }
17930 elsif($DoubleReport)
17931 { # default
17932 writeReport("Binary", getReport("Binary"));
17933 writeReport("Source", getReport("Source"));
17934 }
17935 elsif($BinaryOnly)
17936 { # --binary
17937 writeReport("Binary", getReport("Binary"));
17938 }
17939 elsif($SourceOnly)
17940 { # --source
17941 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017942 }
17943}
17944
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017945sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017946{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017947 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017948
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017949 $Footer .= "<hr/>\n";
17950 $Footer .= "<div class='footer' align='right'>";
17951 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17952 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017953 $Footer .= "<br/>\n";
17954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017955 return $Footer;
17956}
17957
17958sub get_Report_Problems($$)
17959{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017960 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017961
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017962 my $Report = get_Report_TypeProblems($Severity, $Level);
17963 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017964 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017965 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017966
17967 if($Severity eq "Low" or $Severity eq "Safe") {
17968 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017969 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017970
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017971 if($ReportFormat eq "html")
17972 {
17973 if($Report)
17974 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017975 if($JoinReport)
17976 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017977 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017978 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17979 }
17980 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017981 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017984 else
17985 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017986 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017987 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17988 }
17989 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017990 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017992 }
17993 }
17994 }
17995 return $Report;
17996}
17997
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017998sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017999{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018000 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030018001
18002 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
18003 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
18004 $Head .= "<head>\n";
18005 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
18006 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
18007 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
18008 $Head .= "<title>$Title</title>\n";
18009 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
18010 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
18011 $Head .= "</head>\n";
18012
18013 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018014}
18015
18016sub insertIDs($)
18017{
18018 my $Text = $_[0];
18019 while($Text=~/CONTENT_ID/)
18020 {
18021 if(int($Content_Counter)%2) {
18022 $ContentID -= 1;
18023 }
18024 $Text=~s/CONTENT_ID/c_$ContentID/;
18025 $ContentID += 1;
18026 $Content_Counter += 1;
18027 }
18028 return $Text;
18029}
18030
18031sub checkPreprocessedUnit($)
18032{
18033 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018034 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018035 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018036 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018037
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018038 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018039 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018040 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018041 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018042 chomp($Line);
18043 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018044 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018045 $CurHeader = path_format($1, $OSgroup);
18046 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018047 $CurClass = "";
18048
18049 if(index($CurHeader, $TMP_DIR)==0) {
18050 next;
18051 }
18052
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018053 if(substr($CurHeaderName, 0, 1) eq "<")
18054 { # <built-in>, <command-line>, etc.
18055 $CurHeaderName = "";
18056 $CurHeader = "";
18057 }
18058
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018059 if($ExtraInfo)
18060 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018061 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018062 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18063 }
18064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018065 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018066 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018067 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018068 if($CurHeaderName)
18069 {
18070 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18071 and not $Registered_Headers{$Version}{$CurHeader})
18072 { # not a target
18073 next;
18074 }
18075 if(not is_target_header($CurHeaderName, 1)
18076 and not is_target_header($CurHeaderName, 2))
18077 { # user-defined header
18078 next;
18079 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018080 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018081 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018082
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018083 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018084 {
18085 my ($Name, $Value) = ($1, $2);
18086 if(not $Constants{$Version}{$Name}{"Access"})
18087 {
18088 $Constants{$Version}{$Name}{"Access"} = "public";
18089 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018090 if($CurHeaderName) {
18091 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18092 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018093 }
18094 }
18095 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18096 $Constants{$Version}{$1}{"Access"} = "private";
18097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018098 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018099 else
18100 {
18101 if(defined $ExtraDump)
18102 {
18103 if($Line=~/(\w+)\s*\(/)
18104 { # functions
18105 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18106 }
18107 #elsif($Line=~/(\w+)\s*;/)
18108 #{ # data
18109 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18110 #}
18111 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18112 $CurClass = $2;
18113 }
18114 }
18115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018116 }
18117 close(PREPROC);
18118 foreach my $Constant (keys(%{$Constants{$Version}}))
18119 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018120 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18121 {
18122 delete($Constants{$Version}{$Constant});
18123 next;
18124 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018125 if(not $ExtraDump and ($Constant=~/_h\Z/i
18126 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018127 { # skip
18128 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018129 }
18130 else {
18131 delete($Constants{$Version}{$Constant}{"Access"});
18132 }
18133 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018134 if($Debug)
18135 {
18136 mkpath($DEBUG_PATH{$Version});
18137 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018139}
18140
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018141sub uncoverConstant($$)
18142{
18143 my ($LibVersion, $Constant) = @_;
18144 return "" if(not $LibVersion or not $Constant);
18145 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18146 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18147 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18148 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018149
18150 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018151 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018152 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18153 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018154 {
18155 push(@RecurConstant, $Constant);
18156 my $Uncovered = uncoverConstant($LibVersion, $Value);
18157 if($Uncovered ne "") {
18158 $Value = $Uncovered;
18159 }
18160 pop(@RecurConstant);
18161 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018162
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018163 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018164 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018165 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18166 }
18167 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18168}
18169
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018170sub simpleConstant($$)
18171{
18172 my ($LibVersion, $Value) = @_;
18173 if($Value=~/\W/)
18174 {
18175 my $Value_Copy = $Value;
18176 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18177 {
18178 my $Word = $1;
18179 if($Value!~/$Word\s*\(/)
18180 {
18181 my $Val = uncoverConstant($LibVersion, $Word);
18182 if($Val ne "")
18183 {
18184 $Value=~s/\b$Word\b/$Val/g;
18185 }
18186 }
18187 }
18188 }
18189 return $Value;
18190}
18191
18192sub computeValue($)
18193{
18194 my $Value = $_[0];
18195
18196 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18197 return $1;
18198 }
18199
18200 if($Value=~/\A[\d\-\+()]+\Z/) {
18201 return eval($Value);
18202 }
18203
18204 return $Value;
18205}
18206
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018207my %IgnoreConstant = map {$_=>1} (
18208 "VERSION",
18209 "VERSIONCODE",
18210 "VERNUM",
18211 "VERS_INFO",
18212 "PATCHLEVEL",
18213 "INSTALLPREFIX",
18214 "VBUILD",
18215 "VPATCH",
18216 "VMINOR",
18217 "BUILD_STRING",
18218 "BUILD_TIME",
18219 "PACKAGE_STRING",
18220 "PRODUCTION",
18221 "CONFIGURE_COMMAND",
18222 "INSTALLDIR",
18223 "BINDIR",
18224 "CONFIG_FILE_PATH",
18225 "DATADIR",
18226 "EXTENSION_DIR",
18227 "INCLUDE_PATH",
18228 "LIBDIR",
18229 "LOCALSTATEDIR",
18230 "SBINDIR",
18231 "SYSCONFDIR",
18232 "RELEASE",
18233 "SOURCE_ID",
18234 "SUBMINOR",
18235 "MINOR",
18236 "MINNOR",
18237 "MINORVERSION",
18238 "MAJOR",
18239 "MAJORVERSION",
18240 "MICRO",
18241 "MICROVERSION",
18242 "BINARY_AGE",
18243 "INTERFACE_AGE",
18244 "CORE_ABI",
18245 "PATCH",
18246 "COPYRIGHT",
18247 "TIMESTAMP",
18248 "REVISION",
18249 "PACKAGE_TAG",
18250 "PACKAGEDATE",
18251 "NUMVERSION",
18252 "Release",
18253 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018254);
18255
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018256sub constantFilter($$$)
18257{
18258 my ($Name, $Value, $Level) = @_;
18259
18260 if($Level eq "Binary")
18261 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018262 if($Name=~/_t\Z/)
18263 { # __malloc_ptr_t
18264 return 1;
18265 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018266 foreach (keys(%IgnoreConstant))
18267 {
18268 if($Name=~/(\A|_)$_(_|\Z)/)
18269 { # version
18270 return 1;
18271 }
18272 if(/\A[A-Z].*[a-z]\Z/)
18273 {
18274 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18275 { # version
18276 return 1;
18277 }
18278 }
18279 }
18280 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18281 { # version
18282 return 1;
18283 }
18284 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18285 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18286 return 1;
18287 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018288
18289 if($Value=~/\A["'].*['"]/i)
18290 { # string
18291 return 0;
18292 }
18293
18294 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18295 { # static int gcry_pth_init
18296 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018297 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018298 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018299 return 1;
18300 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018301 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018302 { # foo(p)
18303 return 1;
18304 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018305 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018306 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018307 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018308 return 1;
18309 }
18310 }
18311
18312 return 0;
18313}
18314
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018315sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018316{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018317 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018318 foreach my $Constant (keys(%{$Constants{1}}))
18319 {
18320 if($SkipConstants{1}{$Constant})
18321 { # skipped by the user
18322 next;
18323 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018324
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018325 if(my $Header = $Constants{1}{$Constant}{"Header"})
18326 {
18327 if(not is_target_header($Header, 1)
18328 and not is_target_header($Header, 2))
18329 { # user-defined header
18330 next;
18331 }
18332 }
18333 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018334 next;
18335 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018336
18337 my $Old_Value = uncoverConstant(1, $Constant);
18338
18339 if(constantFilter($Constant, $Old_Value, $Level))
18340 { # separate binary and source problems
18341 next;
18342 }
18343
18344 if(not defined $Constants{2}{$Constant}{"Value"})
18345 { # removed
18346 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18347 "Target"=>$Constant,
18348 "Old_Value"=>$Old_Value );
18349 next;
18350 }
18351
18352 if($Constants{2}{$Constant}{"Value"} eq "")
18353 { # empty value
18354 # TODO: implement a rule
18355 next;
18356 }
18357
18358 my $New_Value = uncoverConstant(2, $Constant);
18359
18360 my $Old_Value_Pure = $Old_Value;
18361 my $New_Value_Pure = $New_Value;
18362
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018363 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18364 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18365 $New_Value_Pure=~s/(\W)\s+/$1/g;
18366 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018368 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018369
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018370 if($New_Value_Pure ne $Old_Value_Pure)
18371 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018372 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18373 { # complex values
18374 next;
18375 }
18376 if(computeValue($Old_Value) eq computeValue($New_Value))
18377 { # expressions
18378 next;
18379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018380 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18381 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18382 next;
18383 }
18384 if($Old_Value eq "0" and $New_Value eq "NULL")
18385 { # 0 => NULL
18386 next;
18387 }
18388 if($Old_Value eq "NULL" and $New_Value eq "0")
18389 { # NULL => 0
18390 next;
18391 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018392 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018393 "Target"=>$Constant,
18394 "Old_Value"=>$Old_Value,
18395 "New_Value"=>$New_Value );
18396 }
18397 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018398
18399 foreach my $Constant (keys(%{$Constants{2}}))
18400 {
18401 if(not defined $Constants{1}{$Constant}{"Value"})
18402 {
18403 if($SkipConstants{2}{$Constant})
18404 { # skipped by the user
18405 next;
18406 }
18407
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018408 if(my $Header = $Constants{2}{$Constant}{"Header"})
18409 {
18410 if(not is_target_header($Header, 1)
18411 and not is_target_header($Header, 2))
18412 { # user-defined header
18413 next;
18414 }
18415 }
18416 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018417 next;
18418 }
18419
18420 my $New_Value = uncoverConstant(2, $Constant);
18421 if(not defined $New_Value or $New_Value eq "") {
18422 next;
18423 }
18424
18425 if(constantFilter($Constant, $New_Value, $Level))
18426 { # separate binary and source problems
18427 next;
18428 }
18429
18430 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18431 "Target"=>$Constant,
18432 "New_Value"=>$New_Value );
18433 }
18434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018435}
18436
18437sub convert_integer($)
18438{
18439 my $Value = $_[0];
18440 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018441 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018442 return hex($Value);
18443 }
18444 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018445 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018446 return oct($Value);
18447 }
18448 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018449 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018450 return oct($Value);
18451 }
18452 else {
18453 return $Value;
18454 }
18455}
18456
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018457sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018458{
18459 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018460 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018461 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018462 {
18463 if($LibVersion==1)
18464 {
18465 printMsg("WARNING", "checking headers only");
18466 $CheckHeadersOnly = 1;
18467 }
18468 else {
18469 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18470 }
18471 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018472
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018473 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018474 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018475 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018476
18477 if($CheckUndefined)
18478 {
18479 my %UndefinedLibs = ();
18480
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018481 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18482
18483 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018484 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018485 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018486 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018487 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018488 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018489 if($Symbol_Library{$LibVersion}{$Symbol}
18490 or $DepSymbol_Library{$LibVersion}{$Symbol})
18491 { # exported by target library
18492 next;
18493 }
18494 if(index($Symbol, '@')!=-1)
18495 { # exported default symbol version (@@)
18496 $Symbol=~s/\@/\@\@/;
18497 if($Symbol_Library{$LibVersion}{$Symbol}
18498 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18499 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018500 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018501 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018502 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18503 $UndefinedLibs{$Path} = 1;
18504 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018505 }
18506 }
18507 }
18508 if($ExtraInfo)
18509 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018510 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018511 {
18512 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018513 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018514 foreach (@Paths)
18515 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018516 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018517 my ($Dir, $Name) = separate_path($_);
18518
18519 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018520 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018521 }
18522
18523 $Name = parse_libname($Name, "name", $OStarget);
18524 $Name=~s/\Alib//;
18525
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018526 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018527 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018528
18529 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18530 {
18531 $LibString = " -L".esc($Dir).$LibString;
18532 }
18533
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018534 writeFile($ExtraInfo."/libs-string", $LibString);
18535 }
18536 }
18537 }
18538
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018539 if($ExtraInfo) {
18540 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18541 }
18542
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018543 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018544 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018545 if($#LibPaths!=-1)
18546 {
18547 if(not keys(%{$Symbol_Library{$LibVersion}}))
18548 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018549 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018550 printMsg("WARNING", "checking headers only");
18551 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018552 }
18553 }
18554 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018555
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018556 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018557 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018558}
18559
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018560my %Prefix_Lib_Map=(
18561 # symbols for autodetecting library dependencies (by prefix)
18562 "pthread_" => ["libpthread"],
18563 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18564 "cairo_" => ["libcairo"],
18565 "gtk_" => ["libgtk-x11-2.0"],
18566 "atk_" => ["libatk-1.0"],
18567 "gdk_" => ["libgdk-x11-2.0"],
18568 "gl" => ["libGL"],
18569 "glu" => ["libGLU"],
18570 "popt" => ["libpopt"],
18571 "Py" => ["libpython"],
18572 "jpeg_" => ["libjpeg"],
18573 "BZ2_" => ["libbz2"],
18574 "Fc" => ["libfontconfig"],
18575 "Xft" => ["libXft"],
18576 "SSL_" => ["libssl"],
18577 "sem_" => ["libpthread"],
18578 "snd_" => ["libasound"],
18579 "art_" => ["libart_lgpl_2"],
18580 "dbus_g" => ["libdbus-glib-1"],
18581 "GOMP_" => ["libgomp"],
18582 "omp_" => ["libgomp"],
18583 "cms" => ["liblcms"]
18584);
18585
18586my %Pattern_Lib_Map=(
18587 "SL[a-z]" => ["libslang"]
18588);
18589
18590my %Symbol_Lib_Map=(
18591 # symbols for autodetecting library dependencies (by name)
18592 "pow" => "libm",
18593 "fmod" => "libm",
18594 "sin" => "libm",
18595 "floor" => "libm",
18596 "cos" => "libm",
18597 "dlopen" => "libdl",
18598 "deflate" => "libz",
18599 "inflate" => "libz",
18600 "move_panel" => "libpanel",
18601 "XOpenDisplay" => "libX11",
18602 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018603 "clock_gettime" => "librt",
18604 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018605);
18606
18607sub find_SymbolLibs($$)
18608{
18609 my ($LibVersion, $Symbol) = @_;
18610
18611 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18612 { # debug symbols
18613 return ();
18614 }
18615
18616 my %Paths = ();
18617
18618 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18619 {
18620 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18621 $Paths{$Path} = 1;
18622 }
18623 }
18624
18625 if(my $SymbolPrefix = getPrefix($Symbol))
18626 {
18627 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18628 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18629 }
18630
18631 if(not keys(%Paths))
18632 {
18633 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18634 {
18635 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18636 {
18637 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18638 $Paths{$Path} = 1;
18639 }
18640 }
18641 }
18642 }
18643
18644 if(not keys(%Paths))
18645 {
18646 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18647 {
18648 if($Symbol=~/\A$Prefix/)
18649 {
18650 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18651 {
18652 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18653 $Paths{$Path} = 1;
18654 }
18655 }
18656 }
18657 }
18658 }
18659
18660 if(not keys(%Paths))
18661 {
18662 if($SymbolPrefix)
18663 { # try to find a library by symbol prefix
18664 if($SymbolPrefix eq "inotify" and
18665 index($Symbol, "\@GLIBC")!=-1)
18666 {
18667 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18668 $Paths{$Path} = 1;
18669 }
18670 }
18671 else
18672 {
18673 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18674 $Paths{$Path} = 1;
18675 }
18676 }
18677 }
18678 }
18679
18680 if(my @Paths = keys(%Paths)) {
18681 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18682 }
18683 }
18684 return keys(%Paths);
18685}
18686
18687sub get_LibPath_Prefix($$)
18688{
18689 my ($LibVersion, $Prefix) = @_;
18690
18691 $Prefix = lc($Prefix);
18692 $Prefix=~s/[_]+\Z//g;
18693
18694 foreach ("-2", "2", "-1", "1", "")
18695 { # libgnome-2.so
18696 # libxml2.so
18697 # libdbus-1.so
18698 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18699 return $Path;
18700 }
18701 }
18702 return "";
18703}
18704
18705sub getPrefix($)
18706{
18707 my $Str = $_[0];
18708 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18709 { # XmuValidArea: Xmu
18710 return $1;
18711 }
18712 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18713 { # snfReadFont: snf
18714 return $1;
18715 }
18716 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18717 { # XRRTimes: XRR
18718 return $1;
18719 }
18720 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18721 { # H5HF_delete: H5
18722 return $1;
18723 }
18724 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18725 { # alarm_event_add: alarm_
18726 return $1;
18727 }
18728 elsif($Str=~/\A(([a-z])\2{1,})/i)
18729 { # ffopen
18730 return $1;
18731 }
18732 return "";
18733}
18734
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018735sub getSymbolSize($$)
18736{ # size from the shared library
18737 my ($Symbol, $LibVersion) = @_;
18738 return 0 if(not $Symbol);
18739 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18740 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18741 {
18742 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18743 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18744 {
18745 if($Size<0) {
18746 return -$Size;
18747 }
18748 }
18749 }
18750 return 0;
18751}
18752
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018753sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018754{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18755 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018756 my ($Name, $Type) = @_;
18757
18758 # single
18759 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018760 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018761 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018762 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018763 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018764
18765 # double
18766 if($Name=~/$DEFAULT_STD_PARMS/)
18767 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018768 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018769 {
18770 my ($ShortName, $FuncParams) = split_Signature($Name);
18771
18772 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18773 {
18774 if(index($FParam, "<")!=-1)
18775 {
18776 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18777 my $FParam_N = canonifyName($FParam, "T");
18778 if($FParam_N ne $FParam) {
18779 $Name=~s/\Q$FParam\E/$FParam_N/g;
18780 }
18781 }
18782 }
18783 }
18784 elsif($Type eq "T")
18785 {
18786 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18787
18788 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018789 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018790 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018791 my $FParam = $TParams[0];
18792 foreach my $Pos (1 .. $#TParams)
18793 {
18794 my $TParam = $TParams[$Pos];
18795 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18796 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18797 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018798 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018799 }
18800 }
18801 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018802 if($Type eq "S") {
18803 return formatName($Name, "S");
18804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018805 return $Name;
18806}
18807
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018808sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018809{
18810 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018811 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018812 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018813 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018814 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018815 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018816 next if($tr_name{$Symbol});
18817 $Symbol=~s/[\@\$]+(.*)\Z//;
18818 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018819 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018820 elsif(index($Symbol, "?")==0)
18821 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018822 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018823 }
18824 else
18825 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018826 $tr_name{$Symbol} = $Symbol;
18827 $mangled_name_gcc{$Symbol} = $Symbol;
18828 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 }
18830 }
18831 if($#MnglNames1 > -1)
18832 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018833 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018834 foreach my $MnglName (@MnglNames1)
18835 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018836 if(my $Unmangled = pop(@UnmangledNames))
18837 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018838 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018839 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18840 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18841 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018842 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018843 and $tr_name{$MnglName}=~/vtable for (.+)/)
18844 { # bind class name and v-table symbol
18845 my $ClassName = $1;
18846 $ClassVTable{$ClassName} = $MnglName;
18847 $VTableClass{$MnglName} = $ClassName;
18848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018849 }
18850 }
18851 }
18852 if($#MnglNames2 > -1)
18853 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018854 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 foreach my $MnglName (@MnglNames2)
18856 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018857 if(my $Unmangled = pop(@UnmangledNames))
18858 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018859 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018860 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018862 }
18863 }
18864 return \%tr_name;
18865}
18866
18867sub link_symbol($$$)
18868{
18869 my ($Symbol, $RunWith, $Deps) = @_;
18870 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18871 return 1;
18872 }
18873 if($Deps eq "+Deps")
18874 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018875 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 return 1;
18877 }
18878 }
18879 return 0;
18880}
18881
18882sub link_symbol_internal($$$)
18883{
18884 my ($Symbol, $RunWith, $Where) = @_;
18885 return 0 if(not $Where or not $Symbol);
18886 if($Where->{$RunWith}{$Symbol})
18887 { # the exact match by symbol name
18888 return 1;
18889 }
18890 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18891 { # indirect symbol version, i.e.
18892 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018893 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018894 if($Where->{$RunWith}{$VSym}) {
18895 return 1;
18896 }
18897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018898 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 if($Sym and $Ver)
18900 { # search for the symbol with the same version
18901 # or without version
18902 if($Where->{$RunWith}{$Sym})
18903 { # old: foo@v|foo@@v
18904 # new: foo
18905 return 1;
18906 }
18907 if($Where->{$RunWith}{$Sym."\@".$Ver})
18908 { # old: foo|foo@@v
18909 # new: foo@v
18910 return 1;
18911 }
18912 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18913 { # old: foo|foo@v
18914 # new: foo@@v
18915 return 1;
18916 }
18917 }
18918 return 0;
18919}
18920
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018921sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018922{
18923 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018924 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018925 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018926 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018927 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018928 my $NM = get_CmdPath("nm");
18929 if(not $NM) {
18930 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018931 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018932 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018933 while(<APP>)
18934 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018935 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018936 push(@Imported, $1);
18937 }
18938 }
18939 close(APP);
18940 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018941 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018942 {
18943 my $DumpBinCmd = get_CmdPath("dumpbin");
18944 if(not $DumpBinCmd) {
18945 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18946 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018947 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018948 while(<APP>)
18949 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018950 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18951 push(@Imported, $1);
18952 }
18953 }
18954 close(APP);
18955 }
18956 else
18957 {
18958 my $ReadelfCmd = get_CmdPath("readelf");
18959 if(not $ReadelfCmd) {
18960 exitStatus("Not_Found", "can't find \"readelf\"");
18961 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018962 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018963 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018964 while(<APP>)
18965 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018966 if(defined $symtab)
18967 { # do nothing with symtab
18968 if(index($_, "'.dynsym'")!=-1)
18969 { # dynamic table
18970 $symtab = undef;
18971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018972 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018973 elsif(index($_, "'.symtab'")!=-1)
18974 { # symbol table
18975 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018976 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018977 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018978 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018979 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18980 if($Ndx eq "UND")
18981 { # only imported symbols
18982 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018983 }
18984 }
18985 }
18986 close(APP);
18987 }
18988 return @Imported;
18989}
18990
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018991my %ELF_BIND = map {$_=>1} (
18992 "WEAK",
18993 "GLOBAL"
18994);
18995
18996my %ELF_TYPE = map {$_=>1} (
18997 "FUNC",
18998 "IFUNC",
18999 "OBJECT",
19000 "COMMON"
19001);
19002
19003my %ELF_VIS = map {$_=>1} (
19004 "DEFAULT",
19005 "PROTECTED"
19006);
19007
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019008sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019009{ # read the line of 'readelf' output corresponding to the symbol
19010 my @Info = split(/\s+/, $_[0]);
19011 # Num: Value Size Type Bind Vis Ndx Name
19012 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019013 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019014 shift(@Info); # spaces
19015 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019016
19017 if($#Info==7)
19018 { # UND SYMBOL (N)
19019 if($Info[7]=~/\(\d+\)/) {
19020 pop(@Info);
19021 }
19022 }
19023
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019024 if($#Info!=6)
19025 { # other lines
19026 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019027 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019028 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019029 return () if(not defined $ELF_BIND{$Info[3]});
19030 return () if(not defined $ELF_VIS{$Info[4]});
19031 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19032 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19033 return ();
19034 }
19035 if($OStarget eq "symbian")
19036 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19037 if(index($Info[6], "_._.absent_export_")!=-1)
19038 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19039 return ();
19040 }
19041 $Info[6]=~s/\@.+//g; # remove version
19042 }
19043 if(index($Info[2], "0x") == 0)
19044 { # size == 0x3d158
19045 $Info[2] = hex($Info[2]);
19046 }
19047 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019048}
19049
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019050sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019051{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019052 my ($LibVersion, $Name) = @_;
19053 return "" if(not $LibVersion or not $Name);
19054 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19055 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019056 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019057 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19058}
19059
19060sub get_LibPath_I($$)
19061{
19062 my ($LibVersion, $Name) = @_;
19063 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019064 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019065 if(-f $Name)
19066 { # absolute path
19067 return $Name;
19068 }
19069 else
19070 { # broken
19071 return "";
19072 }
19073 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019074 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019075 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019076 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019077 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019078 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019079 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019080 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 }
19082 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19083 { # ldconfig default paths
19084 return $DefaultPath;
19085 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019086 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019087 { # search in default linker directories
19088 # and then in all system paths
19089 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019090 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019091 }
19092 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019093 if(not defined $Cache{"checkSystemFiles"}) {
19094 checkSystemFiles();
19095 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019096 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19097 return $AllObjects[0];
19098 }
19099 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19100 {
19101 if($ShortName ne $Name)
19102 { # FIXME: check this case
19103 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19104 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019105 }
19106 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019107 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019108 # can't find
19109 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019110}
19111
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019112sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019113{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19115 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019116
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019117 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019118
19119 if(not $Real_Path)
19120 { # broken link
19121 return ();
19122 }
19123
19124 my $Lib_Name = get_filename($Real_Path);
19125
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019126 if($ExtraInfo)
19127 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019128 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019129 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019130 }
19131
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019132 if($IsNeededLib)
19133 {
19134 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19135 return ();
19136 }
19137 }
19138 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019139 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019141 push(@RecurLib, $Lib_Name);
19142 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019143 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19144
19145 if(not $IsNeededLib)
19146 { # special cases: libstdc++ and libc
19147 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19148 {
19149 if($ShortName eq "libstdc++")
19150 { # libstdc++.so.6
19151 $STDCXX_TESTING = 1;
19152 }
19153 elsif($ShortName eq "libc")
19154 { # libc-2.11.3.so
19155 $GLIBC_TESTING = 1;
19156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019157 }
19158 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019159 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019160 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019161 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019162 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019163 mkpath(get_dirname($DebugPath));
19164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 if($OStarget eq "macos")
19166 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019167 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019168 if(not $NM) {
19169 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019170 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019171 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019172 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019173 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019174 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019175 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019176 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019177 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019178 else
19179 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019180 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019182 while(<LIB>)
19183 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019184 if($CheckUndefined)
19185 {
19186 if(not $IsNeededLib)
19187 {
19188 if(/ U _([\w\$]+)\s*\Z/)
19189 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019190 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019191 next;
19192 }
19193 }
19194 }
19195
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019196 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019197 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019198 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019199 if($IsNeededLib)
19200 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019201 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019202 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019203 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19204 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019206 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019207 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019208 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019209 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19210 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019211 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19212 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019213 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019214 setLanguage($LibVersion, "C++");
19215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019217 }
19218 }
19219 }
19220 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019222 if($Deps)
19223 {
19224 if($LIB_TYPE eq "dynamic")
19225 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019226
19227 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019228 if(not $OtoolCmd) {
19229 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019230 }
19231
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019232 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19233 while(<LIB>)
19234 {
19235 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19236 and $1 ne $Lib_Path) {
19237 $NeededLib{$1} = 1;
19238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019239 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019240 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 }
19243 }
19244 elsif($OStarget eq "windows")
19245 { # Windows *.dll, *.lib
19246 my $DumpBinCmd = get_CmdPath("dumpbin");
19247 if(not $DumpBinCmd) {
19248 exitStatus("Not_Found", "can't find \"dumpbin\"");
19249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019250 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019251 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019252 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019253 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019254 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019255 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019256 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019257 else
19258 { # write to pipe
19259 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019261 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019262 {
19263 my $realname = undef;
19264 if($LIB_TYPE eq "dynamic")
19265 {
19266 # 1197 4AC 0000A620 SetThreadStackGuarantee
19267 # 1198 4AD SetThreadToken (forwarded to ...)
19268 # 3368 _o2i_ECPublicKey
19269 # 1 0 00005B30 ??0?N = ... (with pdb)
19270 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19271 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19272 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19273 { # dynamic, static and forwarded symbols
19274 $realname = $1;
19275 }
19276 }
19277 else
19278 { # static
19279 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19280 {
19281 # 16 IID_ISecurityInformation
19282 $realname = $1;
19283 }
19284 }
19285
19286 if($realname)
19287 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019288 if($IsNeededLib)
19289 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019290 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019291 {
19292 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19293 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019295 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019296 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019297 {
19298 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19299 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019300 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19301 {
19302 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19303 setLanguage($LibVersion, "C++");
19304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019306 }
19307 }
19308 }
19309 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019310
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019311 if($Deps)
19312 {
19313 if($LIB_TYPE eq "dynamic")
19314 { # dependencies
19315 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19316 while(<LIB>)
19317 {
19318 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19319 and $1 ne $Lib_Path) {
19320 $NeededLib{path_format($1, $OSgroup)} = 1;
19321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019322 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019323 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019325 }
19326 }
19327 else
19328 { # Unix; *.so, *.a
19329 # Symbian: *.dso, *.lib
19330 my $ReadelfCmd = get_CmdPath("readelf");
19331 if(not $ReadelfCmd) {
19332 exitStatus("Not_Found", "can't find \"readelf\"");
19333 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019334 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019335 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019336 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019337 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019338 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019339 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019340 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019341 else
19342 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019343 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019344 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019345 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019346 while(<LIB>)
19347 {
19348 if($LIB_TYPE eq "dynamic")
19349 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019350 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019351 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019352 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019353 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019354 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019355 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019356 # do nothing with symtab
19357 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019358 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019359 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019360 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019361 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019362 next;
19363 }
19364 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019365 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019366 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019367 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019368 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019369 if($CheckUndefined)
19370 {
19371 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019372 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019373 }
19374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019375 next;
19376 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019377 if($Bind eq "WEAK")
19378 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019379 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019380 if($Weak eq "-Weak")
19381 { # skip WEAK symbols
19382 next;
19383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019385 my $Short = $Symbol;
19386 $Short=~s/\@.+//g;
19387 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019388 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019389 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19390 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019391 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019392 if($IsNeededLib)
19393 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019394 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019395 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019396 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19397 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019400 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019401 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019402 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19403 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19404 if($Vers)
19405 {
19406 if($LIB_EXT eq "so")
19407 { # value
19408 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19409 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019411 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019412 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19413 {
19414 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19415 setLanguage($LibVersion, "C++");
19416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019418 }
19419 }
19420 }
19421 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019422
19423 if($Deps and $LIB_TYPE eq "dynamic")
19424 { # dynamic library specifics
19425 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19426 open(LIB, $Cmd." |");
19427
19428 while(<LIB>)
19429 {
19430 if(/NEEDED.+\[([^\[\]]+)\]/)
19431 { # dependencies:
19432 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19433 $NeededLib{$1} = 1;
19434 }
19435 }
19436
19437 close(LIB);
19438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019439 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019440 if($Vers)
19441 {
19442 if(not $IsNeededLib and $LIB_EXT eq "so")
19443 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019444 my %Found = ();
19445
19446 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019447 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019449 next if(index($Symbol,"\@")==-1);
19450 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019452 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019453 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019454 if($Symbol_SameValue ne $Symbol
19455 and index($Symbol_SameValue,"\@")==-1)
19456 {
19457 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019458 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019459 last;
19460 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019461 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019462 }
19463 }
19464
19465 # default
19466 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19467 {
19468 next if(defined $Found{$Symbol});
19469 next if(index($Symbol,"\@\@")==-1);
19470
19471 if($Symbol=~/\A([^\@]*)\@\@/
19472 and not $SymVer{$LibVersion}{$1})
19473 {
19474 $SymVer{$LibVersion}{$1} = $Symbol;
19475 $Found{$Symbol} = 1;
19476 }
19477 }
19478
19479 # non-default
19480 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19481 {
19482 next if(defined $Found{$Symbol});
19483 next if(index($Symbol,"\@")==-1);
19484
19485 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19486 and not $SymVer{$LibVersion}{$1})
19487 {
19488 $SymVer{$LibVersion}{$1} = $Symbol;
19489 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019490 }
19491 }
19492 }
19493 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019494 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019495 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019496 foreach my $DyLib (sort keys(%NeededLib))
19497 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019498 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19499
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019500 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19501 {
19502 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19503 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19504 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019506 }
19507 }
19508 pop(@RecurLib);
19509 return $Library_Symbol{$LibVersion};
19510}
19511
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019512sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019513{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019514 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019515 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019516 return keys(%Prefixes);
19517}
19518
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019519sub get_prefixes_I($$)
19520{
19521 foreach my $P (@{$_[0]})
19522 {
19523 my @Parts = reverse(split(/[\/\\]+/, $P));
19524 my $Name = $Parts[0];
19525 foreach (1 .. $#Parts)
19526 {
19527 $_[1]->{$Name}{$P} = 1;
19528 last if($_>4 or $Parts[$_] eq "include");
19529 $Name = $Parts[$_].$SLASH.$Name;
19530 }
19531 }
19532}
19533
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019534sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019535{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019536 $Cache{"checkSystemFiles"} = 1;
19537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019538 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019539
19540 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019541 {
19542 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019543
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019544 my @Files = cmd_find($DevelPath,"f");
19545 foreach my $Link (cmd_find($DevelPath,"l"))
19546 { # add symbolic links
19547 if(-f $Link) {
19548 push(@Files, $Link);
19549 }
19550 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019551
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019552 # search for headers in /usr/lib
19553 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19554 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19555 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019556
19557 # search for libraries in /usr/lib (including symbolic links)
19558 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19559 foreach my $Path (@Libs)
19560 {
19561 my $N = get_filename($Path);
19562 $SystemObjects{$N}{$Path} = 1;
19563 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019564 }
19565 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019566
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019567 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019568 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019569 next if(not -d $DevelPath);
19570 # search for all header files in the /usr/include
19571 # with or without extension (ncurses.h, QtCore, ...)
19572 push(@SysHeaders, cmd_find($DevelPath,"f"));
19573 foreach my $Link (cmd_find($DevelPath,"l"))
19574 { # add symbolic links
19575 if(-f $Link) {
19576 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019578 }
19579 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019580 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019581}
19582
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019583sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019584{
19585 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019586 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019587 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19588 {
19589 if(not -e $Dest) {
19590 exitStatus("Access_Error", "can't access \'$Dest\'");
19591 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019592 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019593 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19594 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019595 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019596 }
19597 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019598 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019599}
19600
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019601sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602{
19603 my ($Path, $LibVersion) = @_;
19604 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019605 my $Name = get_filename($Path);
19606 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019607 return 1;
19608 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019609 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019610 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19611 return 1;
19612 }
19613 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19614 {
19615 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19616 return 1;
19617 }
19618 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019619 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019620 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019621 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019622 return 1;
19623 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019624 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625 return 1;
19626 }
19627 }
19628 return 0;
19629}
19630
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019631sub specificHeader($$)
19632{
19633 my ($Header, $Spec) = @_;
19634 my $Name = get_filename($Header);
19635
19636 if($Spec eq "windows")
19637 {# MS Windows
19638 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19639 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19640 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19641 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19642 my @Dirs = (
19643 "win32",
19644 "win64",
19645 "win",
19646 "windows",
19647 "msvcrt"
19648 ); # /gsf-win32/
19649 if(my $DIRs = join("|", @Dirs)) {
19650 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19651 }
19652 }
19653 elsif($Spec eq "macos")
19654 { # Mac OS
19655 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19656 }
19657
19658 return 0;
19659}
19660
19661sub skipAlienHeader($)
19662{
19663 my $Path = $_[0];
19664 my $Name = get_filename($Path);
19665 my $Dir = get_dirname($Path);
19666
19667 if($Tolerance=~/2/)
19668 { # 2 - skip internal headers
19669 my @Terms = (
19670 "p",
19671 "priv",
19672 "int",
19673 "impl",
19674 "implementation",
19675 "internal",
19676 "private",
19677 "old",
19678 "compat",
19679 "debug",
19680 "test",
19681 "gen"
19682 );
19683
19684 my @Dirs = (
19685 "private",
19686 "priv",
19687 "port",
19688 "impl",
19689 "internal",
19690 "detail",
19691 "details",
19692 "old",
19693 "compat",
19694 "debug",
19695 "config",
19696 "compiler",
19697 "platform",
19698 "test"
19699 );
19700
19701 if(my $TERMs = join("|", @Terms)) {
19702 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19703 }
19704 if(my $DIRs = join("|", @Dirs)) {
19705 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19706 }
19707
19708 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19709 }
19710
19711 if($Tolerance=~/1/)
19712 { # 1 - skip non-Linux headers
19713 if($OSgroup ne "windows")
19714 {
19715 if(specificHeader($Path, "windows")) {
19716 return 1;
19717 }
19718 }
19719 if($OSgroup ne "macos")
19720 {
19721 if(specificHeader($Path, "macos")) {
19722 return 1;
19723 }
19724 }
19725 }
19726
19727 # valid
19728 return 0;
19729}
19730
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019731sub skipHeader($$)
19732{
19733 my ($Path, $LibVersion) = @_;
19734 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019735 if(defined $Cache{"skipHeader"}{$Path}) {
19736 return $Cache{"skipHeader"}{$Path};
19737 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019738 if(defined $Tolerance and $Tolerance=~/1|2/)
19739 { # --tolerant
19740 if(skipAlienHeader($Path)) {
19741 return ($Cache{"skipHeader"}{$Path} = 1);
19742 }
19743 }
19744 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19745 return 0;
19746 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019747 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19748}
19749
19750sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019751{ # returns:
19752 # 1 - if header should NOT be included and checked
19753 # 2 - if header should NOT be included, but should be checked
19754 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019755 my $Name = get_filename($Path);
19756 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019757 return $Kind;
19758 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019759 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19760 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019761 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019762 if(index($Path, $D)!=-1)
19763 {
19764 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19765 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019767 }
19768 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019769 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19770 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019772 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19773 {
19774 if($Name=~/$P/) {
19775 return $Kind;
19776 }
19777 if($P=~/[\/\\]/ and $Path=~/$P/) {
19778 return $Kind;
19779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 }
19781 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019783 return 0;
19784}
19785
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019786sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019787{
19788 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019789 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019790 { # system directory
19791 return;
19792 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019793 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019794 { # already registered
19795 return;
19796 }
19797 foreach my $Path (find_libs($Dir,"",1))
19798 {
19799 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019800 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019801 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019802 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019803 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19804}
19805
19806sub registerObject($$)
19807{
19808 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019809
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019810 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019811 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019812 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019813 {
19814 if(my $SONAME = getSONAME($Path)) {
19815 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19816 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019817 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019818 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19819 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019820 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019821
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019822 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019823 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019824 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019825 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019826 if($ObjArch ne getArch_GCC($LibVersion))
19827 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19828 $CheckedArch{$LibVersion} = 1;
19829 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 +040019830 }
19831 }
19832 }
19833}
19834
19835sub getArch_Object($)
19836{
19837 my $Path = $_[0];
19838
19839 my %MachineType = (
19840 "14C" => "x86",
19841 "8664" => "x86_64",
19842 "1C0" => "arm",
19843 "200" => "ia64"
19844 );
19845
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019846 my %ArchName = (
19847 "s390:31-bit" => "s390",
19848 "s390:64-bit" => "s390x",
19849 "powerpc:common" => "ppc32",
19850 "powerpc:common64" => "ppc64",
19851 "i386:x86-64" => "x86_64",
19852 "mips:3000" => "mips",
19853 "sparc:v8plus" => "sparcv9"
19854 );
19855
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019856 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019857 {
19858 my $DumpbinCmd = get_CmdPath("dumpbin");
19859 if(not $DumpbinCmd) {
19860 exitStatus("Not_Found", "can't find \"dumpbin\"");
19861 }
19862
19863 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19864 my $Out = `$Cmd`;
19865
19866 if($Out=~/(\w+)\smachine/)
19867 {
19868 if(my $Type = $MachineType{uc($1)})
19869 {
19870 return $Type;
19871 }
19872 }
19873 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019874 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019875 {
19876 my $ObjdumpCmd = get_CmdPath("objdump");
19877 if(not $ObjdumpCmd) {
19878 exitStatus("Not_Found", "can't find \"objdump\"");
19879 }
19880
19881 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019882
19883 if($OSgroup eq "windows") {
19884 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19885 }
19886 else {
19887 $Cmd = "LANG=$LOCALE ".$Cmd;
19888 }
19889 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019890
19891 if($Out=~/architecture:\s+([\w\-\:]+)/)
19892 {
19893 my $Arch = $1;
19894 if($Arch=~s/\:(.+)//)
19895 {
19896 my $Suffix = $1;
19897
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019898 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019899 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019900 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019901 }
19902 }
19903
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019904 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019905 $Arch = "x86";
19906 }
19907
19908 if($Arch eq "x86-64") {
19909 $Arch = "x86_64";
19910 }
19911
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019912 if($Arch eq "ia64-elf64") {
19913 $Arch = "ia64";
19914 }
19915
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019916 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019917 }
19918 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019919 elsif($OStarget=~/macos/)
19920 {
19921 my $OtoolCmd = get_CmdPath("otool");
19922 if(not $OtoolCmd) {
19923 exitStatus("Not_Found", "can't find \"otool\"");
19924 }
19925
19926 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19927 my $Out = qx/$Cmd/;
19928
19929 if($Out=~/X86_64/i) {
19930 return "x86_64";
19931 }
19932 elsif($Out=~/X86/i) {
19933 return "x86";
19934 }
19935 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019936 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019937 {
19938 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019939 # TODO
19940 }
19941
19942 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019943}
19944
19945sub getSONAME($)
19946{
19947 my $Path = $_[0];
19948 return if(not $Path);
19949 if(defined $Cache{"getSONAME"}{$Path}) {
19950 return $Cache{"getSONAME"}{$Path};
19951 }
19952 my $ObjdumpCmd = get_CmdPath("objdump");
19953 if(not $ObjdumpCmd) {
19954 exitStatus("Not_Found", "can't find \"objdump\"");
19955 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019956 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019957 if($OSgroup eq "windows") {
19958 $SonameCmd .= " | find \"SONAME\"";
19959 }
19960 else {
19961 $SonameCmd .= " | grep SONAME";
19962 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019963 if(my $SonameInfo = `$SonameCmd`)
19964 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019965 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19966 return ($Cache{"getSONAME"}{$Path} = $1);
19967 }
19968 }
19969 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019970}
19971
19972sub getSOPaths_Dest($$)
19973{
19974 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019975 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019976 return ();
19977 }
19978 if(-f $Dest)
19979 {
19980 if(not parse_libname($Dest, "name", $OStarget)) {
19981 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19982 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019983 registerObject($Dest, $LibVersion);
19984 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019985 return ($Dest);
19986 }
19987 elsif(-d $Dest)
19988 {
19989 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019990 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019991 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019992 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19993 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019994 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019995 { # all files and symlinks that match the name of a library
19996 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19997 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019998 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019999 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020000 }
20001 }
20002 }
20003 else
20004 { # search for all files and symlinks
20005 foreach my $Path (find_libs($Dest,"",""))
20006 {
20007 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020008 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020009 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020010 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020011 }
20012 if($OSgroup eq "macos")
20013 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020014 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020015 {
20016 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020017 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020018 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020019 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
20020 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020021 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020022 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020023 }
20024 }
20025 }
20026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020027 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020028 }
20029 else {
20030 return ();
20031 }
20032}
20033
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020034sub realpath_F($)
20035{
20036 my $Path = $_[0];
20037 return path_format(realpath($Path), $OSgroup);
20038}
20039
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020040sub isCyclical($$)
20041{
20042 my ($Stack, $Value) = @_;
20043 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020044}
20045
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020046sub getGCC_Opts($)
20047{ # to use in module
20048 my $LibVersion = $_[0];
20049
20050 my @Opts = ();
20051
20052 if($CompilerOptions{$LibVersion})
20053 { # user-defined options
20054 push(@Opts, $CompilerOptions{$LibVersion});
20055 }
20056 if($GccOptions)
20057 { # additional
20058 push(@Opts, $GccOptions);
20059 }
20060
20061 if(@Opts) {
20062 return join(" ", @Opts);
20063 }
20064
20065 return undef;
20066}
20067
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020068sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020069{
20070 my $LibVersion = $_[0];
20071
20072 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
20073 return $Cache{"getArch_GCC"}{$LibVersion};
20074 }
20075
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020076 if(not $GCC_PATH) {
20077 return undef;
20078 }
20079
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020080 my $Arch = undef;
20081
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020082 if(my $Target = get_dumpmachine($GCC_PATH))
20083 {
20084 if($Target=~/x86_64/) {
20085 $Arch = "x86_64";
20086 }
20087 elsif($Target=~/i[3-6]86/) {
20088 $Arch = "x86";
20089 }
20090 elsif($Target=~/\Aarm/i) {
20091 $Arch = "arm";
20092 }
20093 }
20094
20095 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020096 {
20097 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20098
20099 my $Cmd = $GCC_PATH." test.c -o test";
20100 if(my $Opts = getGCC_Opts($LibVersion))
20101 { # user-defined options
20102 $Cmd .= " ".$Opts;
20103 }
20104
20105 chdir($TMP_DIR);
20106 system($Cmd);
20107 chdir($ORIG_DIR);
20108
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020109 my $EX = join_P($TMP_DIR, "test");
20110
20111 if($OSgroup eq "windows") {
20112 $EX = join_P($TMP_DIR, "test.exe");
20113 }
20114
20115 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020116
20117 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020118 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020119 }
20120
20121 if(not $Arch) {
20122 exitStatus("Error", "can't check ARCH type");
20123 }
20124
20125 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20126}
20127
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020128sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020129{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020130 my $LibVersion = $_[0];
20131
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020132 my $Size = undef;
20133
20134 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020135 if(my $Arch = getArch($LibVersion))
20136 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020137 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020138 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020139 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020140 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20141 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020142 }
20143 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020144
20145 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020146 {
20147 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020148
20149 my $Cmd = $GCC_PATH." -E -dD empty.h";
20150 if(my $Opts = getGCC_Opts($LibVersion))
20151 { # user-defined options
20152 $Cmd .= " ".$Opts;
20153 }
20154
20155 chdir($TMP_DIR);
20156 my $Defines = `$Cmd`;
20157 chdir($ORIG_DIR);
20158
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020159 unlink("$TMP_DIR/empty.h");
20160
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020161 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20162 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020163 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020164 }
20165 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20166 { # GCC 3
20167 my $PTRDIFF = $1;
20168 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020169 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020170 }
20171 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020172 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020173 }
20174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020175 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020176
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020177 if(not $Size) {
20178 exitStatus("Error", "can't check WORD size");
20179 }
20180
20181 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020182}
20183
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020184sub getWordSize($)
20185{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020186 return $WORD_SIZE{$_[0]};
20187}
20188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020189sub majorVersion($)
20190{
20191 my $V = $_[0];
20192 return 0 if(not $V);
20193 my @VParts = split(/\./, $V);
20194 return $VParts[0];
20195}
20196
20197sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020198{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020199 my ($V1, $V2) = @_;
20200 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020201 my @V1Parts = split(/\./, $V1);
20202 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020203 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020205 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20206 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20207 }
20208 return -1 if($#V1Parts < $#V2Parts);
20209 return 1 if($#V1Parts > $#V2Parts);
20210 return 0;
20211}
20212
20213sub read_ABI_Dump($$)
20214{
20215 my ($LibVersion, $Path) = @_;
20216 return if(not $LibVersion or not -e $Path);
20217 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020218 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 { # input *.abi
20220 $FilePath = $Path;
20221 }
20222 else
20223 { # input *.abi.tar.gz
20224 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020225 if(not isDump_U($FilePath)) {
20226 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020228 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020229
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020230 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020231
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020232 my $Line = readLineNum($FilePath, 0);
20233 if($Line=~/xml/)
20234 { # XML format
20235 loadModule("XmlDump");
20236 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020237 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020238 else
20239 { # Perl Data::Dumper format (default)
20240 open(DUMP, $FilePath);
20241 local $/ = undef;
20242 my $Content = <DUMP>;
20243 close(DUMP);
20244
20245 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20246 { # remove temp file
20247 unlink($FilePath);
20248 }
20249 if($Content!~/};\s*\Z/) {
20250 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20251 }
20252 $ABI = eval($Content);
20253 if(not $ABI) {
20254 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020256 }
20257 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020258 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020259 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020260 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020261 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020262 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020263 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020264 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020265 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020266
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020267 if($ABI->{"PublicABI"}) {
20268 $UsedDump{$LibVersion}{"Public"} = 1;
20269 }
20270
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020271 if($ABI->{"ABI_DUMP_VERSION"})
20272 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020273 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020274 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020275 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020276 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020277 }
20278 else
20279 { # support for old ABI dumps
20280 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020281 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020282 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020283 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020284 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020285
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020286 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020287 {
20288 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 +040020289 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020290
20291 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20292 { # DWARF ABI Dump
20293 $UseConv_Real{$LibVersion}{"P"} = 1;
20294 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20295
20296 $UsedDump{$LibVersion}{"DWARF"} = 1;
20297
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020298 if(not $TargetComponent_Opt)
20299 {
20300 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20301 $TargetComponent = "module";
20302 }
20303 else {
20304 $TargetComponent = "object";
20305 }
20306 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020307 }
20308
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020309 if(not checkDump($LibVersion, "2.11"))
20310 { # old ABI dumps
20311 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020312 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020313 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020314 { # ABI dump created with --binary option
20315 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20316 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020317 else
20318 { # default
20319 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20320 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020321
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020322 if(defined $ABI->{"Mode"}
20323 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020324 { # --ext option
20325 $ExtendedCheck = 1;
20326 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020327 if($ABI->{"Extra"}) {
20328 $ExtraDump = 1;
20329 }
20330
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020331 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020332 {
20333 $UsedDump{$LibVersion}{"L"} = $Lang;
20334 setLanguage($LibVersion, $Lang);
20335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020336 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020337 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020338 }
20339 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020340 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020341 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020342 if(not $TInfo)
20343 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020344 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020345 }
20346 my %Tid_TDid = ();
20347 foreach my $TDid (keys(%{$TInfo}))
20348 {
20349 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20350 {
20351 $MAX_ID = $Tid if($Tid>$MAX_ID);
20352 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020353 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020354 }
20355 }
20356 my %NewID = ();
20357 foreach my $Tid (keys(%Tid_TDid))
20358 {
20359 my @TDids = keys(%{$Tid_TDid{$Tid}});
20360 if($#TDids>=1)
20361 {
20362 foreach my $TDid (@TDids)
20363 {
20364 if($TDid) {
20365 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20366 }
20367 else
20368 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020369 my $ID = ++$MAX_ID;
20370
20371 $NewID{$TDid}{$Tid} = $ID;
20372 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20373 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020374 }
20375 }
20376 }
20377 else
20378 {
20379 my $TDid = $TDids[0];
20380 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20381 }
20382 }
20383 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20384 {
20385 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20386 if(defined $Info{"BaseType"})
20387 {
20388 my $Bid = $Info{"BaseType"}{"Tid"};
20389 my $BDid = $Info{"BaseType"}{"TDid"};
20390 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020391 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020392 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20393 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20394 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020395 }
20396 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020398 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020399 read_Machine_DumpInfo($ABI, $LibVersion);
20400 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020401 if(not $SymbolInfo{$LibVersion})
20402 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020403 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020404 }
20405 if(not keys(%{$SymbolInfo{$LibVersion}}))
20406 { # validation of old-version dumps
20407 if(not $ExtendedCheck) {
20408 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20409 }
20410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020411 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020412 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020413 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020414 else
20415 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020416 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020417 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020418 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020419 }
20420 if(not $DepSymbols)
20421 { # Cannot reconstruct DepSymbols. This may result in false
20422 # positives if the old dump is for library 2. Not a problem if
20423 # old dumps are only from old libraries.
20424 $DepSymbols = {};
20425 }
20426 foreach my $Symbol (keys(%{$DepSymbols})) {
20427 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020429 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020430 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020431
20432 if(my $V = $TargetVersion{$LibVersion}) {
20433 $Descriptor{$LibVersion}{"Version"} = $V;
20434 }
20435 else {
20436 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20437 }
20438
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020439 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020440 { # if not defined by -skip-types option
20441 if(defined $ABI->{"SkipTypes"})
20442 {
20443 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20444 {
20445 $SkipTypes{$LibVersion}{$TName} = 1;
20446 }
20447 }
20448 if(defined $ABI->{"OpaqueTypes"})
20449 { # support for old dumps
20450 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20451 {
20452 $SkipTypes{$LibVersion}{$TName} = 1;
20453 }
20454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020455 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020456
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020457 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020458 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020459 if(defined $ABI->{"SkipSymbols"}) {
20460 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20461 }
20462 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020463 { # support for old dumps
20464 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20465 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020466 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020467 { # support for old dumps
20468 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020470 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020471 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020472
20473 if(not $TargetHeaders{$LibVersion})
20474 { # if not defined by -headers-list option
20475 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20476 }
20477
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020478 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020479 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020480 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020482 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020483 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020484 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020485
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020486 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020487 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020488
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020489 if(not checkDump($LibVersion, "2.10.1")
20490 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020491 { # support for old ABI dumps: added target headers
20492 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020493 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020494 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020495
20496 if(not $ABI->{"PublicABI"})
20497 {
20498 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20499 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20500 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020502 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020503 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020504 if(defined $ABI->{"GccConstants"})
20505 { # 3.0
20506 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20507 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20508 }
20509 }
20510
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020511 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020512 if(not $NestedNameSpaces{$LibVersion})
20513 { # support for old dumps
20514 # Cannot reconstruct NameSpaces. This may affect design
20515 # of the compatibility report.
20516 $NestedNameSpaces{$LibVersion} = {};
20517 }
20518 # target system type
20519 # needed to adopt HTML report
20520 if(not $DumpSystem)
20521 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020522 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020523 }
20524 # recreate environment
20525 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20526 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020527 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020528 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020529 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20530 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020531 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020532 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020533 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020534 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20535 {
20536 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20537 setLanguage($LibVersion, "C++");
20538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020539 }
20540 }
20541 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020542 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20543 {
20544 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20545 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20546 }
20547 }
20548
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020550 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020551 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020552 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020553 {
20554 if(not $Symbol_Library{$LibVersion}{$MnglName}
20555 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20556 push(@VFunc, $MnglName);
20557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020558 }
20559 }
20560 translateSymbols(@VFunc, $LibVersion);
20561 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020562 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20563
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020564 if(not checkDump($LibVersion, "3.0"))
20565 { # support for old ABI dumps
20566 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20567 {
20568 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20569 {
20570 if(ref($BaseType) eq "HASH") {
20571 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20572 }
20573 }
20574 }
20575 }
20576
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020577 if(not checkDump($LibVersion, "3.2"))
20578 { # support for old ABI dumps
20579 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20580 {
20581 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20582 {
20583 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20584 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20585 }
20586 }
20587 }
20588
20589 # repair target headers list
20590 delete($TargetHeaders{$LibVersion});
20591 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020592 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20593 }
20594 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20595 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020596 }
20597
20598 # non-target constants from anon enums
20599 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20600 {
20601 if(not $ExtraDump
20602 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20603 {
20604 delete($Constants{$LibVersion}{$Name});
20605 }
20606 }
20607 }
20608
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020609 if(not checkDump($LibVersion, "2.20"))
20610 { # support for old ABI dumps
20611 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20612 {
20613 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20614
20615 if($TType=~/Struct|Union|Enum|Typedef/)
20616 { # repair complex types first
20617 next;
20618 }
20619
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020620 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020621 {
20622 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20623 if($BType=~/Struct|Union|Enum/i)
20624 {
20625 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20626 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20627 }
20628 }
20629 }
20630 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20631 {
20632 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20633 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20634 if($TType=~/Struct|Union|Enum/) {
20635 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20636 }
20637 }
20638 }
20639
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020640 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020641 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020642 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20643 { # support for old ABI dumps < 2.0 (ACC 1.22)
20644 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20645 {
20646 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20647 {
20648 if($Access ne "public") {
20649 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20650 }
20651 }
20652 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20653 }
20654 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20655 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020656 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20657 { # support for old ABI dumps
20658 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20659 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020660 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20661 { # DWARF ABI Dumps
20662 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20663 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020664 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20665 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20666 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020667
20668 # support for old formatting of type names
20669 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20670
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020671 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20672 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020673 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020674 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20675 {
20676 if($SubId eq $TypeId)
20677 { # Fix erroneus ABI dump
20678 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20679 next;
20680 }
20681
20682 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020683 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020684 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020685 if($TInfo{"Type"} eq "MethodPtr")
20686 {
20687 if(defined $TInfo{"Param"})
20688 { # support for old ABI dumps <= 1.17
20689 if(not defined $TInfo{"Param"}{"0"})
20690 {
20691 my $Max = keys(%{$TInfo{"Param"}});
20692 foreach my $Pos (1 .. $Max) {
20693 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20694 }
20695 delete($TInfo{"Param"}{$Max});
20696 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20697 }
20698 }
20699 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020700 if($TInfo{"BaseType"} eq $TypeId)
20701 { # fix ABI dump
20702 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20703 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020704
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020705 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020706 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020707 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020708 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020709 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20710 if(not $BName)
20711 { # broken type
20712 next;
20713 }
20714 if($TInfo{"Name"} eq $BName)
20715 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020716 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020717 next;
20718 }
20719 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20720 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020721 }
20722 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020723 }
20724 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20725 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020726 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020727 }
20728 }
20729
20730 if(not checkDump($LibVersion, "2.15"))
20731 { # support for old ABI dumps
20732 my %Dups = ();
20733 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20734 {
20735 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020736 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020737 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20738 { # remove template decls
20739 delete($SymbolInfo{$LibVersion}{$InfoId});
20740 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020742 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020743 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20744 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020745 { # templates
20746 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020747 }
20748 }
20749 }
20750
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020751 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20752 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020753 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20754 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20755 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20756 { # support for old ABI dumps (< 3.1)
20757 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20758 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20759 { # add "this" first parameter
20760 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20761 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20762
20763 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20764 {
20765 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20766 foreach my $Pos (reverse(0 .. $#Pos)) {
20767 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20768 }
20769 }
20770 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20771 }
20772 }
20773
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020774 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20775 { # ABI dumps have no mangled names for C-functions
20776 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20777 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020778 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20779 { # support for old ABI dumps
20780 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20781 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020782 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20783 { # DWARF ABI Dumps
20784 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20785 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020786 }
20787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020788 $Descriptor{$LibVersion}{"Dump"} = 1;
20789}
20790
20791sub read_Machine_DumpInfo($$)
20792{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020793 my ($ABI, $LibVersion) = @_;
20794 if($ABI->{"Arch"}) {
20795 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020797 if($ABI->{"WordSize"}) {
20798 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020799 }
20800 else
20801 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020802 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020803 }
20804 if(not $WORD_SIZE{$LibVersion})
20805 { # support for old dumps (<1.23)
20806 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20807 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020808 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020809 }
20810 else
20811 {
20812 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020813 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020814 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020815 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20816 { # any "pointer"-type
20817 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020818 last;
20819 }
20820 }
20821 if($PSize)
20822 { # a pointer type size
20823 $WORD_SIZE{$LibVersion} = $PSize;
20824 }
20825 else {
20826 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20827 }
20828 }
20829 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020830 if($ABI->{"GccVersion"}) {
20831 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020832 }
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030020833 elsif($ABI->{"ClangVersion"}) {
20834 $CLANG_VERSION{$LibVersion} = $ABI->{"ClangVersion"};
20835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020836}
20837
20838sub read_Libs_DumpInfo($$)
20839{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020840 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020841 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20842 if(not $Library_Symbol{$LibVersion})
20843 { # support for old dumps
20844 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020846 if(keys(%{$Library_Symbol{$LibVersion}})
20847 and not $DumpAPI) {
20848 $Descriptor{$LibVersion}{"Libs"} = "OK";
20849 }
20850}
20851
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020852sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020853{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020854 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020855
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020856 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020857 and not $DumpAPI) {
20858 $Descriptor{$LibVersion}{"Headers"} = "OK";
20859 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020860 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020861 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020862 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020863 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020864 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020865
20866 if(keys(%{$ABI->{"Sources"}})
20867 and not $DumpAPI) {
20868 $Descriptor{$LibVersion}{"Sources"} = "OK";
20869 }
20870 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020871 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020872 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20873 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020875}
20876
20877sub find_libs($$$)
20878{
20879 my ($Path, $Type, $MaxDepth) = @_;
20880 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020881 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882}
20883
20884sub createDescriptor($$)
20885{
20886 my ($LibVersion, $Path) = @_;
20887 if(not $LibVersion or not $Path
20888 or not -e $Path) {
20889 return "";
20890 }
20891 if(-d $Path)
20892 { # directory with headers files and shared objects
20893 return "
20894 <version>
20895 ".$TargetVersion{$LibVersion}."
20896 </version>
20897
20898 <headers>
20899 $Path
20900 </headers>
20901
20902 <libs>
20903 $Path
20904 </libs>";
20905 }
20906 else
20907 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020908 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020909 { # standard XML-descriptor
20910 return readFile($Path);
20911 }
20912 elsif(is_header($Path, 2, $LibVersion))
20913 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020914 $CheckHeadersOnly = 1;
20915
20916 if($LibVersion==1) {
20917 $TargetVersion{$LibVersion} = "X";
20918 }
20919
20920 if($LibVersion==2) {
20921 $TargetVersion{$LibVersion} = "Y";
20922 }
20923
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020924 return "
20925 <version>
20926 ".$TargetVersion{$LibVersion}."
20927 </version>
20928
20929 <headers>
20930 $Path
20931 </headers>
20932
20933 <libs>
20934 none
20935 </libs>";
20936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020937 else
20938 { # standard XML-descriptor
20939 return readFile($Path);
20940 }
20941 }
20942}
20943
20944sub detect_lib_default_paths()
20945{
20946 my %LPaths = ();
20947 if($OSgroup eq "bsd")
20948 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020949 if(my $LdConfig = get_CmdPath("ldconfig"))
20950 {
20951 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20952 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020953 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20954 {
20955 my $Name = "lib".$1;
20956 if(not defined $LPaths{$Name}) {
20957 $LPaths{$Name} = $2;
20958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 }
20960 }
20961 }
20962 else {
20963 printMsg("WARNING", "can't find ldconfig");
20964 }
20965 }
20966 else
20967 {
20968 if(my $LdConfig = get_CmdPath("ldconfig"))
20969 {
20970 if($SystemRoot and $OSgroup eq "linux")
20971 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20972 if(-e $SystemRoot."/etc/ld.so.conf") {
20973 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20974 }
20975 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020976 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20977 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020978 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20979 {
20980 my ($Name, $Path) = ($1, $2);
20981 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020982 if(not defined $LPaths{$Name})
20983 { # get first element from the list of available paths
20984
20985 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20986 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20987 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20988
20989 $LPaths{$Name} = $Path;
20990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020991 }
20992 }
20993 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020994 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020995 printMsg("WARNING", "can't find ldconfig");
20996 }
20997 }
20998 return \%LPaths;
20999}
21000
21001sub detect_bin_default_paths()
21002{
21003 my $EnvPaths = $ENV{"PATH"};
21004 if($OSgroup eq "beos") {
21005 $EnvPaths.=":".$ENV{"BETOOLS"};
21006 }
21007 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021008 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021009 {
21010 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021011 next if(not $Path);
21012 if($SystemRoot
21013 and $Path=~/\A\Q$SystemRoot\E\//)
21014 { # do NOT use binaries from target system
21015 next;
21016 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021017 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021018 }
21019}
21020
21021sub detect_inc_default_paths()
21022{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021023 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021024 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021025 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021026 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021027 next if(index($Line, "/cc1plus ")!=-1);
21028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021029 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
21030 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021031 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021032 if(index($Path, "c++")!=-1
21033 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021034 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021035 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021036 if(not defined $MAIN_CPP_DIR
21037 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
21038 $MAIN_CPP_DIR = $Path;
21039 }
21040 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 elsif(index($Path, "gcc")!=-1) {
21042 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021043 }
21044 else
21045 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021046 if($Path=~/local[\/\\]+include/)
21047 { # local paths
21048 next;
21049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021050 if($SystemRoot
21051 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
21052 { # The GCC include path for user headers is not a part of the system root
21053 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
21054 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
21055 next;
21056 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021057 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021058 }
21059 }
21060 }
21061 unlink("$TMP_DIR/empty.h");
21062 return %DPaths;
21063}
21064
21065sub detect_default_paths($)
21066{
21067 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
21068 my $Search = $_[0];
21069 if($Search!~/inc/) {
21070 $HSearch = 0;
21071 }
21072 if($Search!~/lib/) {
21073 $LSearch = 0;
21074 }
21075 if($Search!~/bin/) {
21076 $BSearch = 0;
21077 }
21078 if($Search!~/gcc/) {
21079 $GSearch = 0;
21080 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021081 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021082 { # <search_headers> section of the XML descriptor
21083 # do NOT search for systems headers
21084 $HSearch = 0;
21085 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021086 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021087 { # <search_libs> section of the XML descriptor
21088 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089 $LSearch = 0;
21090 }
21091 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21092 { # additional search paths
21093 next if($Type eq "include" and not $HSearch);
21094 next if($Type eq "lib" and not $LSearch);
21095 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021096 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021097 }
21098 if($OSgroup ne "windows")
21099 { # unix-like
21100 foreach my $Type ("include", "lib", "bin")
21101 { # automatic detection of system "devel" directories
21102 next if($Type eq "include" and not $HSearch);
21103 next if($Type eq "lib" and not $LSearch);
21104 next if($Type eq "bin" and not $BSearch);
21105 my ($UsrDir, $RootDir) = ("/usr", "/");
21106 if($SystemRoot and $Type ne "bin")
21107 { # 1. search for target headers and libraries
21108 # 2. use host commands: ldconfig, readelf, etc.
21109 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21110 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021111 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021112 if(-d $RootDir."/".$Type)
21113 { # if "/lib" is symbolic link
21114 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021115 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021116 }
21117 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021118 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021119 }
21120 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021121 if(-d $UsrDir)
21122 {
21123 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021124 if(-d $UsrDir."/".$Type)
21125 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021126 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021127 }
21128 }
21129 }
21130 }
21131 if($BSearch)
21132 {
21133 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021134 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021135 }
21136 # check environment variables
21137 if($OSgroup eq "beos")
21138 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021139 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021140 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021141 if($_ eq ".") {
21142 next;
21143 }
21144 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21145 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21146 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021147 }
21148 }
21149 if($HSearch)
21150 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021151 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21152 split(/:|;/, $ENV{"BEINCLUDES"})
21153 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021154 }
21155 if($LSearch)
21156 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021157 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21158 split(/:|;/, $ENV{"BELIBRARIES"}),
21159 split(/:|;/, $ENV{"LIBRARY_PATH"})
21160 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161 }
21162 }
21163 if($LSearch)
21164 { # using linker to get system paths
21165 if(my $LPaths = detect_lib_default_paths())
21166 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021167 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021168 foreach my $Name (keys(%{$LPaths}))
21169 {
21170 if($SystemRoot
21171 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21172 { # wrong ldconfig configuration
21173 # check your <sysroot>/etc/ld.so.conf
21174 next;
21175 }
21176 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021177 if(my $Dir = get_dirname($LPaths->{$Name})) {
21178 $Dirs{$Dir} = 1;
21179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021180 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021181 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021182 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021183 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021184 }
21185 if($BSearch)
21186 {
21187 if($CrossGcc)
21188 { # --cross-gcc=arm-linux-gcc
21189 if(-e $CrossGcc)
21190 { # absolute or relative path
21191 $GCC_PATH = get_abs_path($CrossGcc);
21192 }
21193 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21194 { # command name
21195 $GCC_PATH = $CrossGcc;
21196 }
21197 else {
21198 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21199 }
21200 if($GCC_PATH=~/\s/) {
21201 $GCC_PATH = "\"".$GCC_PATH."\"";
21202 }
21203 }
21204 }
21205 if($GSearch)
21206 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021207 if(not $CrossGcc)
21208 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021209 $GCC_PATH = get_CmdPath("gcc");
21210 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021211 if(not $GCC_PATH)
21212 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021213 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021214 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021215 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021216 { # select the latest version
21217 @GCCs = sort {$b cmp $a} @GCCs;
21218 if(check_gcc($GCCs[0], "3"))
21219 {
21220 $GCC_PATH = $GCCs[0];
21221 last;
21222 }
21223 }
21224 }
21225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021226 if(not $GCC_PATH) {
21227 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21228 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021229
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021230 my $GCC_Ver = get_dumpversion($GCC_PATH);
21231 if($GCC_Ver eq "4.8")
21232 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21233 my $Info = `$GCC_PATH --version`;
21234
21235 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21236 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21237 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21238 $GCC_Ver = $2;
21239 }
21240 }
21241
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021242 if($OStarget=~/macos/)
21243 {
21244 my $Info = `$GCC_PATH --version`;
21245
21246 if($Info=~/clang/i) {
21247 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21248 }
21249 }
21250
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021251 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021253 my $GccTarget = get_dumpmachine($GCC_PATH);
21254
21255 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021256 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021257 $OStarget = "linux";
21258 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021259 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021260 elsif($GccTarget=~/symbian/)
21261 {
21262 $OStarget = "symbian";
21263 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21264 }
21265
21266 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21267
21268 # check GCC version
21269 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21270 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021271 # introduced in 4.8 and fixed in 4.8.3
21272 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.");
21273
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021274 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021275 }
21276 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021277 else {
21278 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021279 }
21280 }
21281 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021282 {
21283 # GCC standard paths
21284 if($GCC_PATH and not $NoStdInc)
21285 {
21286 my %DPaths = detect_inc_default_paths();
21287 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21288 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21289 @DefaultIncPaths = @{$DPaths{"Inc"}};
21290 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21291 }
21292
21293 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021294 my $IncPath = "/usr/include";
21295 if($SystemRoot) {
21296 $IncPath = $SystemRoot.$IncPath;
21297 }
21298 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021299 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021300 }
21301 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021302
21303 if($ExtraInfo)
21304 {
21305 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21306 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308}
21309
21310sub getLIB_EXT($)
21311{
21312 my $Target = $_[0];
21313 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21314 return $Ext;
21315 }
21316 return $OS_LibExt{$LIB_TYPE}{"default"};
21317}
21318
21319sub getAR_EXT($)
21320{
21321 my $Target = $_[0];
21322 if(my $Ext = $OS_Archive{$Target}) {
21323 return $Ext;
21324 }
21325 return $OS_Archive{"default"};
21326}
21327
21328sub get_dumpversion($)
21329{
21330 my $Cmd = $_[0];
21331 return "" if(not $Cmd);
21332 if($Cache{"get_dumpversion"}{$Cmd}) {
21333 return $Cache{"get_dumpversion"}{$Cmd};
21334 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021335 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021336 chomp($V);
21337 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21338}
21339
21340sub get_dumpmachine($)
21341{
21342 my $Cmd = $_[0];
21343 return "" if(not $Cmd);
21344 if($Cache{"get_dumpmachine"}{$Cmd}) {
21345 return $Cache{"get_dumpmachine"}{$Cmd};
21346 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021347 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021348 chomp($Machine);
21349 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21350}
21351
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021352sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021353{
21354 my $Cmd = $_[0];
21355 return "" if(not $Cmd);
21356 my @Options = (
21357 "--version",
21358 "-help"
21359 );
21360 foreach my $Opt (@Options)
21361 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021362 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363 if($Info) {
21364 return 1;
21365 }
21366 }
21367 return 0;
21368}
21369
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021370sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021371{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021372 my ($Cmd, $ReqVer) = @_;
21373 return 0 if(not $Cmd or not $ReqVer);
21374 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21375 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021377 if(my $GccVer = get_dumpversion($Cmd))
21378 {
21379 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21380 if(cmpVersions($GccVer, $ReqVer)>=0) {
21381 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21382 }
21383 }
21384 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021385}
21386
21387sub get_depth($)
21388{
21389 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021390 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021391 }
21392 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21393}
21394
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021395sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021396{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021397 return if($Cache{"registerGccHeaders"}); # this function should be called once
21398
21399 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021401 my @Headers = cmd_find($Path,"f");
21402 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21403 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021404 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021405 my $FileName = get_filename($HPath);
21406 if(not defined $DefaultGccHeader{$FileName})
21407 { # skip duplicated
21408 $DefaultGccHeader{$FileName} = $HPath;
21409 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021410 }
21411 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021412 $Cache{"registerGccHeaders"} = 1;
21413}
21414
21415sub registerCppHeaders()
21416{
21417 return if($Cache{"registerCppHeaders"}); # this function should be called once
21418
21419 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021420 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021421 my @Headers = cmd_find($CppDir,"f");
21422 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21423 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021424 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021425 my $FileName = get_filename($Path);
21426 if(not defined $DefaultCppHeader{$FileName})
21427 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 $DefaultCppHeader{$FileName} = $Path;
21429 }
21430 }
21431 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021432 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021433}
21434
21435sub parse_libname($$$)
21436{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021437 return "" if(not $_[0]);
21438 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21439 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021440 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021441 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21442}
21443
21444sub parse_libname_I($$$)
21445{
21446 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021447
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021448 if($Target eq "symbian") {
21449 return parse_libname_symbian($Name, $Type);
21450 }
21451 elsif($Target eq "windows") {
21452 return parse_libname_windows($Name, $Type);
21453 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021454
21455 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021456 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021457 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021458 { # libSDL-1.2.so.0.7.1
21459 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021460 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021461 if($Type eq "name")
21462 { # libSDL-1.2
21463 # libwbxml2
21464 return $2;
21465 }
21466 elsif($Type eq "name+ext")
21467 { # libSDL-1.2.so
21468 # libwbxml2.so
21469 return $1;
21470 }
21471 elsif($Type eq "version")
21472 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021473 if(defined $7
21474 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021475 { # 0.7.1
21476 return $7;
21477 }
21478 else
21479 { # libc-2.5.so (=>2.5 version)
21480 my $MV = $5;
21481 $MV=~s/\A[\-\_]+//g;
21482 return $MV;
21483 }
21484 }
21485 elsif($Type eq "short")
21486 { # libSDL
21487 # libwbxml2
21488 return $3;
21489 }
21490 elsif($Type eq "shortest")
21491 { # SDL
21492 # wbxml
21493 return shortest_name($3);
21494 }
21495 }
21496 return "";# error
21497}
21498
21499sub parse_libname_symbian($$)
21500{
21501 my ($Name, $Type) = @_;
21502 my $Ext = getLIB_EXT("symbian");
21503 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21504 { # libpthread{00010001}.dso
21505 if($Type eq "name")
21506 { # libpthread{00010001}
21507 return $2;
21508 }
21509 elsif($Type eq "name+ext")
21510 { # libpthread{00010001}.dso
21511 return $1;
21512 }
21513 elsif($Type eq "version")
21514 { # 00010001
21515 my $V = $4;
21516 $V=~s/\{(.+)\}/$1/;
21517 return $V;
21518 }
21519 elsif($Type eq "short")
21520 { # libpthread
21521 return $3;
21522 }
21523 elsif($Type eq "shortest")
21524 { # pthread
21525 return shortest_name($3);
21526 }
21527 }
21528 return "";# error
21529}
21530
21531sub parse_libname_windows($$)
21532{
21533 my ($Name, $Type) = @_;
21534 my $Ext = getLIB_EXT("windows");
21535 if($Name=~/((.+?)\.$Ext)\Z/)
21536 { # netapi32.dll
21537 if($Type eq "name")
21538 { # netapi32
21539 return $2;
21540 }
21541 elsif($Type eq "name+ext")
21542 { # netapi32.dll
21543 return $1;
21544 }
21545 elsif($Type eq "version")
21546 { # DLL version embedded
21547 # at binary-level
21548 return "";
21549 }
21550 elsif($Type eq "short")
21551 { # netapi32
21552 return $2;
21553 }
21554 elsif($Type eq "shortest")
21555 { # netapi
21556 return shortest_name($2);
21557 }
21558 }
21559 return "";# error
21560}
21561
21562sub shortest_name($)
21563{
21564 my $Name = $_[0];
21565 # remove prefix
21566 $Name=~s/\A(lib|open)//;
21567 # remove suffix
21568 $Name=~s/[\W\d_]+\Z//i;
21569 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21570 return $Name;
21571}
21572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021573sub createSymbolsList($$$$$)
21574{
21575 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021576
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021577 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021578 prepareSymbols(1);
21579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021580 my %SymbolHeaderLib = ();
21581 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021583 # Get List
21584 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21585 {
21586 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021587 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021588 next;
21589 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021590 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021591 { # skip other symbols
21592 next;
21593 }
21594 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21595 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021596 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021597 next;
21598 }
21599 my $DyLib = $Symbol_Library{1}{$Symbol};
21600 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021601 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021602 next;
21603 }
21604 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21605 $Total+=1;
21606 }
21607 # Draw List
21608 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21609 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21610 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21611 {
21612 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21613 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021614 my %NS_Symbol = ();
21615 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021616 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021617 }
21618 foreach my $NameSpace (sort keys(%NS_Symbol))
21619 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021620 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021621 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21622 foreach my $Symbol (@SortedInterfaces)
21623 {
21624 my $SubReport = "";
21625 my $Signature = get_Signature($Symbol, 1);
21626 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021627 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021628 }
21629 if($Symbol=~/\A(_Z|\?)/)
21630 {
21631 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021632 $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 +040021633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 else {
21635 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21636 }
21637 }
21638 else
21639 {
21640 if($Signature) {
21641 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21642 }
21643 else {
21644 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21645 }
21646 }
21647 $SYMBOLS_LIST .= $SubReport;
21648 }
21649 }
21650 $SYMBOLS_LIST .= "<br/>\n";
21651 }
21652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021653 # clear info
21654 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21655 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21656 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21657 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021658 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021659 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021660 my $CssStyles = readModule("Styles", "SymbolsList.css");
21661 my $JScripts = readModule("Scripts", "Sections.js");
21662 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021663 my $Title = "$LName: public symbols";
21664 my $Keywords = "$LName, API, symbols";
21665 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021666 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021667 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021668 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021669 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021670 writeFile($SaveTo, $SYMBOLS_LIST);
21671}
21672
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021673sub add_target_libs($)
21674{
21675 foreach (@{$_[0]}) {
21676 $TargetLibs{$_} = 1;
21677 }
21678}
21679
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021680sub is_target_lib($)
21681{
21682 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021683 if(not $LName) {
21684 return 0;
21685 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021686 if($OSgroup eq "windows") {
21687 $LName = lc($LName);
21688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021689 if($TargetLibraryName
21690 and $LName!~/\Q$TargetLibraryName\E/) {
21691 return 0;
21692 }
21693 if(keys(%TargetLibs)
21694 and not $TargetLibs{$LName}
21695 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21696 return 0;
21697 }
21698 return 1;
21699}
21700
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021701sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021702{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021703 my ($H, $V) = @_;
21704 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021705 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021706 if($TargetHeaders{$V}{$H}) {
21707 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021708 }
21709 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021710 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021711}
21712
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021713sub readLibs($)
21714{
21715 my $LibVersion = $_[0];
21716 if($OStarget eq "windows")
21717 { # dumpbin.exe will crash
21718 # without VS Environment
21719 check_win32_env();
21720 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021721 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021722 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021723 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021724}
21725
21726sub dump_sorting($)
21727{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021728 my $Hash = $_[0];
21729 return [] if(not $Hash);
21730 my @Keys = keys(%{$Hash});
21731 return [] if($#Keys<0);
21732 if($Keys[0]=~/\A\d+\Z/)
21733 { # numbers
21734 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021735 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021736 else
21737 { # strings
21738 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021739 }
21740}
21741
21742sub printMsg($$)
21743{
21744 my ($Type, $Msg) = @_;
21745 if($Type!~/\AINFO/) {
21746 $Msg = $Type.": ".$Msg;
21747 }
21748 if($Type!~/_C\Z/) {
21749 $Msg .= "\n";
21750 }
21751 if($Quiet)
21752 { # --quiet option
21753 appendFile($COMMON_LOG_PATH, $Msg);
21754 }
21755 else
21756 {
21757 if($Type eq "ERROR") {
21758 print STDERR $Msg;
21759 }
21760 else {
21761 print $Msg;
21762 }
21763 }
21764}
21765
21766sub exitStatus($$)
21767{
21768 my ($Code, $Msg) = @_;
21769 printMsg("ERROR", $Msg);
21770 exit($ERROR_CODE{$Code});
21771}
21772
21773sub exitReport()
21774{ # the tool has run without any errors
21775 printReport();
21776 if($COMPILE_ERRORS)
21777 { # errors in headers may add false positives/negatives
21778 exit($ERROR_CODE{"Compile_Error"});
21779 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021780 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21781 { # --binary
21782 exit($ERROR_CODE{"Incompatible"});
21783 }
21784 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21785 { # --source
21786 exit($ERROR_CODE{"Incompatible"});
21787 }
21788 elsif($RESULT{"Source"}{"Problems"}
21789 or $RESULT{"Binary"}{"Problems"})
21790 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021791 exit($ERROR_CODE{"Incompatible"});
21792 }
21793 else {
21794 exit($ERROR_CODE{"Compatible"});
21795 }
21796}
21797
21798sub readRules($)
21799{
21800 my $Kind = $_[0];
21801 if(not -f $RULES_PATH{$Kind}) {
21802 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21803 }
21804 my $Content = readFile($RULES_PATH{$Kind});
21805 while(my $Rule = parseTag(\$Content, "rule"))
21806 {
21807 my $RId = parseTag(\$Rule, "id");
21808 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21809 foreach my $Prop (@Properties) {
21810 if(my $Value = parseTag(\$Rule, lc($Prop)))
21811 {
21812 $Value=~s/\n[ ]*//;
21813 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21814 }
21815 }
21816 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21817 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21818 }
21819 else {
21820 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21821 }
21822 }
21823}
21824
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021825sub getReportPath($)
21826{
21827 my $Level = $_[0];
21828 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21829 if($Level eq "Binary")
21830 {
21831 if($BinaryReportPath)
21832 { # --bin-report-path
21833 return $BinaryReportPath;
21834 }
21835 elsif($OutputReportPath)
21836 { # --report-path
21837 return $OutputReportPath;
21838 }
21839 else
21840 { # default
21841 return $Dir."/abi_compat_report.$ReportFormat";
21842 }
21843 }
21844 elsif($Level eq "Source")
21845 {
21846 if($SourceReportPath)
21847 { # --src-report-path
21848 return $SourceReportPath;
21849 }
21850 elsif($OutputReportPath)
21851 { # --report-path
21852 return $OutputReportPath;
21853 }
21854 else
21855 { # default
21856 return $Dir."/src_compat_report.$ReportFormat";
21857 }
21858 }
21859 else
21860 {
21861 if($OutputReportPath)
21862 { # --report-path
21863 return $OutputReportPath;
21864 }
21865 else
21866 { # default
21867 return $Dir."/compat_report.$ReportFormat";
21868 }
21869 }
21870}
21871
21872sub printStatMsg($)
21873{
21874 my $Level = $_[0];
21875 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21876}
21877
21878sub listAffected($)
21879{
21880 my $Level = $_[0];
21881 my $List = "";
21882 foreach (keys(%{$TotalAffected{$Level}}))
21883 {
21884 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21885 { # skip "Low"-severity problems
21886 next;
21887 }
21888 $List .= "$_\n";
21889 }
21890 my $Dir = get_dirname(getReportPath($Level));
21891 if($Level eq "Binary") {
21892 writeFile($Dir."/abi_affected.txt", $List);
21893 }
21894 elsif($Level eq "Source") {
21895 writeFile($Dir."/src_affected.txt", $List);
21896 }
21897}
21898
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021899sub printReport()
21900{
21901 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021902 createReport();
21903 if($JoinReport or $DoubleReport)
21904 {
21905 if($RESULT{"Binary"}{"Problems"}
21906 or $RESULT{"Source"}{"Problems"}) {
21907 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021909 else {
21910 printMsg("INFO", "result: COMPATIBLE");
21911 }
21912 printStatMsg("Binary");
21913 printStatMsg("Source");
21914 if($ListAffected)
21915 { # --list-affected
21916 listAffected("Binary");
21917 listAffected("Source");
21918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021920 elsif($BinaryOnly)
21921 {
21922 if($RESULT{"Binary"}{"Problems"}) {
21923 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21924 }
21925 else {
21926 printMsg("INFO", "result: COMPATIBLE");
21927 }
21928 printStatMsg("Binary");
21929 if($ListAffected)
21930 { # --list-affected
21931 listAffected("Binary");
21932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021934 elsif($SourceOnly)
21935 {
21936 if($RESULT{"Source"}{"Problems"}) {
21937 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21938 }
21939 else {
21940 printMsg("INFO", "result: COMPATIBLE");
21941 }
21942 printStatMsg("Source");
21943 if($ListAffected)
21944 { # --list-affected
21945 listAffected("Source");
21946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021948 if($StdOut)
21949 {
21950 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021951 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021952 printMsg("INFO", "compatibility report has been generated to stdout");
21953 }
21954 else
21955 { # default
21956 printMsg("INFO", "compatibility reports have been generated to stdout");
21957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021959 else
21960 {
21961 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021962 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021963 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21964 }
21965 elsif($DoubleReport)
21966 { # default
21967 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21968 }
21969 elsif($BinaryOnly)
21970 { # --binary
21971 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21972 }
21973 elsif($SourceOnly)
21974 { # --source
21975 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021977 }
21978}
21979
21980sub check_win32_env()
21981{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021982 if(not $ENV{"VCINSTALLDIR"}
21983 or not $ENV{"INCLUDE"}) {
21984 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021985 }
21986}
21987
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021988sub diffSets($$)
21989{
21990 my ($S1, $S2) = @_;
21991 my @SK1 = keys(%{$S1});
21992 my @SK2 = keys(%{$S2});
21993 if($#SK1!=$#SK2) {
21994 return 1;
21995 }
21996 foreach my $K1 (@SK1)
21997 {
21998 if(not defined $S2->{$K1}) {
21999 return 1;
22000 }
22001 }
22002 return 0;
22003}
22004
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022005sub defaultDumpPath($$)
22006{
22007 my ($N, $V) = @_;
22008 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
22009}
22010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022011sub create_ABI_Dump()
22012{
22013 if(not -e $DumpAPI) {
22014 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
22015 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022016
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022017 if(isDump($DumpAPI)) {
22018 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022019 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022020 else {
22021 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022022 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022023
22024 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022025 { # set to default: N
22026 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022027 }
22028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022029 initLogging(1);
22030 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022031
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022032 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022033 if($OutputDumpPath)
22034 { # user defined path
22035 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022036 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022037 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
22038
22039 if(not $Archive and not $StdOut)
22040 { # check archive utilities
22041 if($OSgroup eq "windows")
22042 { # using zip
22043 my $ZipCmd = get_CmdPath("zip");
22044 if(not $ZipCmd) {
22045 exitStatus("Not_Found", "can't find \"zip\"");
22046 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022047 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022048 else
22049 { # using tar and gzip
22050 my $TarCmd = get_CmdPath("tar");
22051 if(not $TarCmd) {
22052 exitStatus("Not_Found", "can't find \"tar\"");
22053 }
22054 my $GzipCmd = get_CmdPath("gzip");
22055 if(not $GzipCmd) {
22056 exitStatus("Not_Found", "can't find \"gzip\"");
22057 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022058 }
22059 }
22060
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022061 if(not $Descriptor{1}{"Dump"})
22062 {
22063 if(not $CheckHeadersOnly) {
22064 readLibs(1);
22065 }
22066 if($CheckHeadersOnly) {
22067 setLanguage(1, "C++");
22068 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022069 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022070 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022071 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022072 if(not $Descriptor{1}{"Dump"})
22073 {
22074 if($Descriptor{1}{"Headers"}) {
22075 readHeaders(1);
22076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022077 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022078 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022079 if(not keys(%{$SymbolInfo{1}}))
22080 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022081 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022082 {
22083 if($CheckHeadersOnly) {
22084 exitStatus("Empty_Set", "the set of public symbols is empty");
22085 }
22086 else {
22087 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22088 }
22089 }
22090 }
22091 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022092 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022093 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22094 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022095 if($ExtraDump)
22096 { # add unmangled names to the ABI dump
22097 my @Names = ();
22098 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22099 {
22100 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22101 push(@Names, $MnglName);
22102 }
22103 }
22104 translateSymbols(@Names, 1);
22105 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22106 {
22107 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22108 {
22109 if(my $Unmangled = $tr_name{$MnglName})
22110 {
22111 if($MnglName ne $Unmangled) {
22112 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22113 }
22114 }
22115 }
22116 }
22117 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022118
22119 my %GccConstants = (); # built-in GCC constants
22120 foreach my $Name (keys(%{$Constants{1}}))
22121 {
22122 if(not defined $Constants{1}{$Name}{"Header"})
22123 {
22124 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22125 delete($Constants{1}{$Name});
22126 }
22127 }
22128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022129 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022130 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131 "TypeInfo" => $TypeInfo{1},
22132 "SymbolInfo" => $SymbolInfo{1},
22133 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022134 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022135 "SymbolVersion" => $SymVer{1},
22136 "LibraryVersion" => $Descriptor{1}{"Version"},
22137 "LibraryName" => $TargetLibraryName,
22138 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022139 "SkipTypes" => $SkipTypes{1},
22140 "SkipSymbols" => $SkipSymbols{1},
22141 "SkipNameSpaces" => $SkipNameSpaces{1},
22142 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022143 "Headers" => \%HeadersInfo,
22144 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022145 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022146 "NameSpaces" => $NestedNameSpaces{1},
22147 "Target" => $OStarget,
22148 "Arch" => getArch(1),
22149 "WordSize" => $WORD_SIZE{1},
22150 "GccVersion" => get_dumpversion($GCC_PATH),
22151 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22152 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22153 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022154 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022155 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022156 }
22157 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022158 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022160 if($ExtendedCheck)
22161 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022162 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022164 if($BinaryOnly)
22165 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022166 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022167 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022168 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022169 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022170 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022171 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22172 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022173 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022174
22175 my $ABI_DUMP = "";
22176 if($UseXML)
22177 {
22178 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022179 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022180 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022181 else
22182 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022183 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022185 if($StdOut)
22186 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022187 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022188 printMsg("INFO", "ABI dump has been generated to stdout");
22189 return;
22190 }
22191 else
22192 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022193 my ($DDir, $DName) = separate_path($DumpPath);
22194 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022195 if(not $Archive) {
22196 $DPath = $DumpPath;
22197 }
22198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022199 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022200
22201 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022202 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022203 close(DUMP);
22204
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022205 if(not -s $DPath) {
22206 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22207 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022208 if($Archive) {
22209 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022210 }
22211
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022212 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022213 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022214 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022215 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022216 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022217 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022218 # 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 +040022219 }
22220}
22221
22222sub quickEmptyReports()
22223{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022224 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022225 # NOTE: the dump contains the "LibraryVersion" attribute
22226 # if you change the version, then your dump will be different
22227 # OVERCOME: use -v1 and v2 options for comparing dumps
22228 # and don't change version in the XML descriptor (and dumps)
22229 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022230 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22231 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022232 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022233 my $FilePath1 = $Descriptor{1}{"Path"};
22234 my $FilePath2 = $Descriptor{2}{"Path"};
22235
22236 if(not isDump_U($FilePath1)) {
22237 $FilePath1 = unpackDump($FilePath1);
22238 }
22239
22240 if(not isDump_U($FilePath2)) {
22241 $FilePath2 = unpackDump($FilePath2);
22242 }
22243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022244 if($FilePath1 and $FilePath2)
22245 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022246 my $Line = readLineNum($FilePath1, 0);
22247 if($Line=~/xml/)
22248 { # XML format
22249 # is not supported yet
22250 return;
22251 }
22252
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022253 local $/ = undef;
22254
22255 open(DUMP1, $FilePath1);
22256 my $Content1 = <DUMP1>;
22257 close(DUMP1);
22258
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022259 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022260
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022261 if($FilePath1 eq $FilePath2) {
22262 $Eq = 1;
22263 }
22264
22265 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022266 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022267 open(DUMP2, $FilePath2);
22268 my $Content2 = <DUMP2>;
22269 close(DUMP2);
22270
22271 if($Content1 eq $Content2) {
22272 $Eq = 1;
22273 }
22274
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022275 # clean memory
22276 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022277 }
22278
22279 if($Eq)
22280 {
22281 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022282 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022283 my $ABIdump = eval($Content1);
22284
22285 # clean memory
22286 undef $Content1;
22287
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022288 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022289 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 +040022290 }
22291 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022292 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022293 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22294 }
22295 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022296 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022297 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22298 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022299 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022300
22301 foreach (keys(%{$Registered_Headers{1}})) {
22302 $TargetHeaders{1}{$_} = 1;
22303 }
22304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022305 read_Libs_DumpInfo($ABIdump, 1);
22306 read_Machine_DumpInfo($ABIdump, 1);
22307 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022308
22309 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22310 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22311
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022312 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22313 {
22314 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22315 {
22316 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22317 next;
22318 }
22319 }
22320
22321 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22322 if($Access ne "private")
22323 {
22324 $CheckedSymbols{"Binary"}{$S} = 1;
22325 $CheckedSymbols{"Source"}{$S} = 1;
22326 }
22327 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022329 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22330 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022331
Andrey Ponomarenko1b16ee82016-08-20 23:52:11 +030022332 if(not defined $Descriptor{1}{"Version"}) {
22333 $Descriptor{1}{"Version"} = "X";
22334 }
22335
22336 if(not defined $Descriptor{2}{"Version"}) {
22337 $Descriptor{2}{"Version"} = "Y";
22338 }
22339
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022340 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22341 {
22342 $UsedDump{1}{"DWARF"} = 1;
22343 $UsedDump{2}{"DWARF"} = 1;
22344
22345 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22346 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22347 }
22348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022349 exitReport();
22350 }
22351 }
22352 }
22353}
22354
22355sub initLogging($)
22356{
22357 my $LibVersion = $_[0];
22358 # create log directory
22359 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22360 if($OutputLogPath{$LibVersion})
22361 { # user-defined by -log-path option
22362 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22363 }
22364 if($LogMode ne "n") {
22365 mkpath($LOG_DIR);
22366 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022367 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022368 if($Debug)
22369 { # debug directory
22370 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022371
22372 if(not $ExtraInfo)
22373 { # enable --extra-info
22374 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022376 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022377 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022378}
22379
22380sub writeLog($$)
22381{
22382 my ($LibVersion, $Msg) = @_;
22383 if($LogMode ne "n") {
22384 appendFile($LOG_PATH{$LibVersion}, $Msg);
22385 }
22386}
22387
22388sub resetLogging($)
22389{
22390 my $LibVersion = $_[0];
22391 if($LogMode!~/a|n/)
22392 { # remove old log
22393 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022394 if($Debug) {
22395 rmtree($DEBUG_PATH{$LibVersion});
22396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022397 }
22398}
22399
22400sub printErrorLog($)
22401{
22402 my $LibVersion = $_[0];
22403 if($LogMode ne "n") {
22404 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22405 }
22406}
22407
22408sub isDump($)
22409{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022410 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22411 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022412 return $1;
22413 }
22414 return 0;
22415}
22416
22417sub isDump_U($)
22418{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022419 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022420 return $1;
22421 }
22422 return 0;
22423}
22424
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022425sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022426{
22427 # read input XML descriptors or ABI dumps
22428 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022429 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022430 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022431 if(not -e $Descriptor{1}{"Path"}) {
22432 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022433 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022435 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022436 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022437 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022438 if(not -e $Descriptor{2}{"Path"}) {
22439 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022440 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022443
22444 if(not defined $DisableQuickEmptyReport)
22445 {
22446 if(isDump($Descriptor{1}{"Path"})
22447 and isDump($Descriptor{2}{"Path"}))
22448 { # optimization: equal ABI dumps
22449 quickEmptyReports();
22450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022451 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022453 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022454
22455 if(isDump($Descriptor{1}{"Path"})) {
22456 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022457 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022458 else {
22459 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22460 }
22461
22462 if(isDump($Descriptor{2}{"Path"})) {
22463 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22464 }
22465 else {
22466 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022467 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022468
22469 if(not $Descriptor{1}{"Version"})
22470 { # set to default: X
22471 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022472 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022473 }
22474
22475 if(not $Descriptor{2}{"Version"})
22476 { # set to default: Y
22477 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022478 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022479 }
22480
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022481 if(not $UsedDump{1}{"V"}) {
22482 initLogging(1);
22483 }
22484
22485 if(not $UsedDump{2}{"V"}) {
22486 initLogging(2);
22487 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022488
22489 # check input data
22490 if(not $Descriptor{1}{"Headers"}) {
22491 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022492 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022493 if(not $Descriptor{2}{"Headers"}) {
22494 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022495 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022496
22497 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022498 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022499 if(not $Descriptor{1}{"Libs"}) {
22500 exitStatus("Error", "can't find libraries info in descriptor d1");
22501 }
22502 if(not $Descriptor{2}{"Libs"}) {
22503 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022504 }
22505 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022506
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022507 if($UseDumps)
22508 { # --use-dumps
22509 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022510 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22511 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022512
22513 unlink($DumpPath1);
22514 unlink($DumpPath2);
22515
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022516 my $pid = fork();
22517 if($pid)
22518 { # dump on two CPU cores
22519 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22520 if($RelativeDirectory{1}) {
22521 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22522 }
22523 if($OutputLogPath{1}) {
22524 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22525 }
22526 if($CrossGcc) {
22527 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22528 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022529 if($Quiet)
22530 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022531 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022532 @PARAMS = (@PARAMS, "-logging-mode", "a");
22533 }
22534 elsif($LogMode and $LogMode ne "w")
22535 { # "w" is default
22536 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022537 }
22538 if($ExtendedCheck) {
22539 @PARAMS = (@PARAMS, "-extended");
22540 }
22541 if($UserLang) {
22542 @PARAMS = (@PARAMS, "-lang", $UserLang);
22543 }
22544 if($TargetVersion{1}) {
22545 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022547 if($BinaryOnly) {
22548 @PARAMS = (@PARAMS, "-binary");
22549 }
22550 if($SourceOnly) {
22551 @PARAMS = (@PARAMS, "-source");
22552 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022553 if($SortDump) {
22554 @PARAMS = (@PARAMS, "-sort");
22555 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022556 if($DumpFormat and $DumpFormat ne "perl") {
22557 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22558 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022559 if($CheckHeadersOnly) {
22560 @PARAMS = (@PARAMS, "-headers-only");
22561 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022562 if($Debug)
22563 {
22564 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022565 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022567 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022568 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022569 exit(1);
22570 }
22571 }
22572 else
22573 { # child
22574 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22575 if($RelativeDirectory{2}) {
22576 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22577 }
22578 if($OutputLogPath{2}) {
22579 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22580 }
22581 if($CrossGcc) {
22582 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22583 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022584 if($Quiet)
22585 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022586 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022587 @PARAMS = (@PARAMS, "-logging-mode", "a");
22588 }
22589 elsif($LogMode and $LogMode ne "w")
22590 { # "w" is default
22591 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022592 }
22593 if($ExtendedCheck) {
22594 @PARAMS = (@PARAMS, "-extended");
22595 }
22596 if($UserLang) {
22597 @PARAMS = (@PARAMS, "-lang", $UserLang);
22598 }
22599 if($TargetVersion{2}) {
22600 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22601 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022602 if($BinaryOnly) {
22603 @PARAMS = (@PARAMS, "-binary");
22604 }
22605 if($SourceOnly) {
22606 @PARAMS = (@PARAMS, "-source");
22607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022608 if($SortDump) {
22609 @PARAMS = (@PARAMS, "-sort");
22610 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022611 if($DumpFormat and $DumpFormat ne "perl") {
22612 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22613 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022614 if($CheckHeadersOnly) {
22615 @PARAMS = (@PARAMS, "-headers-only");
22616 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022617 if($Debug)
22618 {
22619 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022620 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022622 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022623 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022624 exit(1);
22625 }
22626 else {
22627 exit(0);
22628 }
22629 }
22630 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022632 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022633 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22634 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022635 if($TargetTitle ne $TargetLibraryName) {
22636 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022637 }
22638 if($ShowRetVal) {
22639 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22640 }
22641 if($CrossGcc) {
22642 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22643 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022644 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22645 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022646 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022647 }
22648 if($ReportFormat and $ReportFormat ne "html")
22649 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022650 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022652 if($OutputReportPath) {
22653 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22654 }
22655 if($BinaryReportPath) {
22656 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22657 }
22658 if($SourceReportPath) {
22659 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22660 }
22661 if($LoggingPath) {
22662 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22663 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022664 if($CheckHeadersOnly) {
22665 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22666 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022667 if($BinaryOnly) {
22668 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22669 }
22670 if($SourceOnly) {
22671 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022673 if($Debug)
22674 {
22675 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22676 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022678 system("perl", $0, @CMP_PARAMS);
22679 exit($?>>8);
22680 }
22681 if(not $Descriptor{1}{"Dump"}
22682 or not $Descriptor{2}{"Dump"})
22683 { # need GCC toolchain to analyze
22684 # header files and libraries
22685 detect_default_paths("inc|lib|gcc");
22686 }
22687 if(not $Descriptor{1}{"Dump"})
22688 {
22689 if(not $CheckHeadersOnly) {
22690 readLibs(1);
22691 }
22692 if($CheckHeadersOnly) {
22693 setLanguage(1, "C++");
22694 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022695 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022696 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022697 }
22698 if(not $Descriptor{2}{"Dump"})
22699 {
22700 if(not $CheckHeadersOnly) {
22701 readLibs(2);
22702 }
22703 if($CheckHeadersOnly) {
22704 setLanguage(2, "C++");
22705 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022706 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022707 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022708 }
22709 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22710 { # support for old ABI dumps
22711 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022712 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022713 {
22714 $WORD_SIZE{1} = $WORD_SIZE{2};
22715 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22716 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022717 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022718 {
22719 $WORD_SIZE{2} = $WORD_SIZE{1};
22720 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22721 }
22722 }
22723 elsif(not $WORD_SIZE{1}
22724 and not $WORD_SIZE{2})
22725 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022726 $WORD_SIZE{1} = "4";
22727 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022728 }
22729 if($Descriptor{1}{"Dump"})
22730 { # support for old ABI dumps
22731 prepareTypes(1);
22732 }
22733 if($Descriptor{2}{"Dump"})
22734 { # support for old ABI dumps
22735 prepareTypes(2);
22736 }
22737 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22738 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22739 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022740 # process input data
22741 if($Descriptor{1}{"Headers"}
22742 and not $Descriptor{1}{"Dump"}) {
22743 readHeaders(1);
22744 }
22745 if($Descriptor{2}{"Headers"}
22746 and not $Descriptor{2}{"Dump"}) {
22747 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022748 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022749
22750 # clean memory
22751 %SystemHeaders = ();
22752 %mangled_name_gcc = ();
22753
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022754 prepareSymbols(1);
22755 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022756
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022757 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022758 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022759
22760 # Virtual Tables
22761 registerVTable(1);
22762 registerVTable(2);
22763
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022764 if(not checkDump(1, "1.22")
22765 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022766 { # support for old ABI dumps
22767 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22768 {
22769 if($ClassName=~/</)
22770 { # templates
22771 if(not defined $VirtualTable{1}{$ClassName})
22772 { # synchronize
22773 delete($VirtualTable{2}{$ClassName});
22774 }
22775 }
22776 }
22777 }
22778
22779 registerOverriding(1);
22780 registerOverriding(2);
22781
22782 setVirtFuncPositions(1);
22783 setVirtFuncPositions(2);
22784
22785 # Other
22786 addParamNames(1);
22787 addParamNames(2);
22788
22789 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022790}
22791
22792sub compareAPIs($)
22793{
22794 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022795
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022796 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022797 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022798
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022799 if($Level eq "Binary") {
22800 printMsg("INFO", "comparing ABIs ...");
22801 }
22802 else {
22803 printMsg("INFO", "comparing APIs ...");
22804 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022805
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022806 if($CheckHeadersOnly
22807 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022808 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022809 detectAdded_H($Level);
22810 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022811 }
22812 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022813 { # added/removed in libs
22814 detectAdded($Level);
22815 detectRemoved($Level);
22816 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022817
22818 mergeSymbols($Level);
22819 if(keys(%{$CheckedSymbols{$Level}})) {
22820 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022821 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022822
22823 $Cache{"mergeTypes"} = (); # free memory
22824
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022825 if($CheckHeadersOnly
22826 or $Level eq "Source")
22827 { # added/removed in headers
22828 mergeHeaders($Level);
22829 }
22830 else
22831 { # added/removed in libs
22832 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022833 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022834
22835 foreach my $S (keys(%{$CompatProblems{$Level}}))
22836 {
22837 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22838 {
22839 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22840 {
22841 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22842 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22843 }
22844 }
22845 }
22846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022847}
22848
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022849sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022850{
22851 my %Opts = (
22852 "OStarget"=>$OStarget,
22853 "Debug"=>$Debug,
22854 "Quiet"=>$Quiet,
22855 "LogMode"=>$LogMode,
22856 "CheckHeadersOnly"=>$CheckHeadersOnly,
22857
22858 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022859 "GCC_PATH"=>$GCC_PATH,
22860 "TargetSysInfo"=>$TargetSysInfo,
22861 "CrossPrefix"=>$CrossPrefix,
22862 "TargetLibraryName"=>$TargetLibraryName,
22863 "CrossGcc"=>$CrossGcc,
22864 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022865 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko991da682016-09-07 19:09:50 +030022866 "CxxIncompat"=>$CxxIncompat,
22867 "SkipUnidentified"=>$SkipUnidentified,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022868
22869 "BinaryOnly" => $BinaryOnly,
22870 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022871 );
22872 return \%Opts;
22873}
22874
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022875sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022876{
22877 my %CODE_ERROR = reverse(%ERROR_CODE);
22878 return $CODE_ERROR{$_[0]};
22879}
22880
22881sub scenario()
22882{
22883 if($StdOut)
22884 { # enable quiet mode
22885 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022886 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022887 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022888 if(not $LogMode)
22889 { # default
22890 $LogMode = "w";
22891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022892 if($UserLang)
22893 { # --lang=C++
22894 $UserLang = uc($UserLang);
22895 $COMMON_LANGUAGE{1}=$UserLang;
22896 $COMMON_LANGUAGE{2}=$UserLang;
22897 }
22898 if($LoggingPath)
22899 {
22900 $OutputLogPath{1} = $LoggingPath;
22901 $OutputLogPath{2} = $LoggingPath;
22902 if($Quiet) {
22903 $COMMON_LOG_PATH = $LoggingPath;
22904 }
22905 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022906
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022907 if($Quick) {
22908 $ADD_TMPL_INSTANCES = 0;
22909 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022910 if($OutputDumpPath)
22911 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022912 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022913 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22914 }
22915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022916 if($BinaryOnly and $SourceOnly)
22917 { # both --binary and --source
22918 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022919 if(not $CmpSystems)
22920 {
22921 $BinaryOnly = 0;
22922 $SourceOnly = 0;
22923 }
22924
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022925 $DoubleReport = 1;
22926 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022927
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022928 if($OutputReportPath)
22929 { # --report-path
22930 $DoubleReport = 0;
22931 $JoinReport = 1;
22932 }
22933 }
22934 elsif($BinaryOnly or $SourceOnly)
22935 { # --binary or --source
22936 $DoubleReport = 0;
22937 $JoinReport = 0;
22938 }
22939 if($UseXML)
22940 { # --xml option
22941 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022942 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022944 if($ReportFormat)
22945 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022946 $ReportFormat = lc($ReportFormat);
22947 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022948 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022950 if($ReportFormat eq "htm")
22951 { # HTM == HTML
22952 $ReportFormat = "html";
22953 }
22954 elsif($ReportFormat eq "xml")
22955 { # --report-format=XML equal to --xml
22956 $UseXML = 1;
22957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022958 }
22959 else
22960 { # default: HTML
22961 $ReportFormat = "html";
22962 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022963 if($DumpFormat)
22964 { # validate
22965 $DumpFormat = lc($DumpFormat);
22966 if($DumpFormat!~/\A(xml|perl)\Z/) {
22967 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22968 }
22969 if($DumpFormat eq "xml")
22970 { # --dump-format=XML equal to --xml
22971 $UseXML = 1;
22972 }
22973 }
22974 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022975 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022976 $DumpFormat = "perl";
22977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022978 if($Quiet and $LogMode!~/a|n/)
22979 { # --quiet log
22980 if(-f $COMMON_LOG_PATH) {
22981 unlink($COMMON_LOG_PATH);
22982 }
22983 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022984 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022985 $CheckUndefined = 1;
22986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022987 if($TestTool and $UseDumps)
22988 { # --test && --use-dumps == --test-dump
22989 $TestDump = 1;
22990 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022991 if($Tolerant)
22992 { # enable all
22993 $Tolerance = 1234;
22994 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022995 if($Help)
22996 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022997 HELP_MESSAGE();
22998 exit(0);
22999 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030023000 if($InfoMsg)
23001 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023002 INFO_MESSAGE();
23003 exit(0);
23004 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023005 if($ShowVersion)
23006 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023007 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 +040023008 exit(0);
23009 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023010 if($DumpVersion)
23011 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023012 printMsg("INFO", $TOOL_VERSION);
23013 exit(0);
23014 }
23015 if($ExtendedCheck) {
23016 $CheckHeadersOnly = 1;
23017 }
23018 if($SystemRoot_Opt)
23019 { # user defined root
23020 if(not -e $SystemRoot_Opt) {
23021 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
23022 }
23023 $SystemRoot = $SystemRoot_Opt;
23024 $SystemRoot=~s/[\/]+\Z//g;
23025 if($SystemRoot) {
23026 $SystemRoot = get_abs_path($SystemRoot);
23027 }
23028 }
23029 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023030
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023031 if($SortDump)
23032 {
23033 $Data::Dumper::Useperl = 1;
23034 $Data::Dumper::Sortkeys = \&dump_sorting;
23035 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040023036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023037 if($TargetLibsPath)
23038 {
23039 if(not -f $TargetLibsPath) {
23040 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
23041 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023042 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
23043 {
23044 if($OSgroup eq "windows") {
23045 $TargetLibs{lc($Lib)} = 1;
23046 }
23047 else {
23048 $TargetLibs{$Lib} = 1;
23049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023050 }
23051 }
23052 if($TargetHeadersPath)
23053 { # --headers-list
23054 if(not -f $TargetHeadersPath) {
23055 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
23056 }
23057 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
23058 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023059 $TargetHeaders{1}{get_filename($Header)} = 1;
23060 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023061 }
23062 }
23063 if($TargetHeader)
23064 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030023065 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
23066 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023067 }
23068 if($TestTool
23069 or $TestDump)
23070 { # --test, --test-dump
23071 detect_default_paths("bin|gcc"); # to compile libs
23072 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023073 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030023074 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023075 exit(0);
23076 }
23077 if($DumpSystem)
23078 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030023079 if(-d $MODULES_DIR."/Targets/"
23080 and -d $MODULES_DIR."/Targets/".$OStarget) {
23081 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
23082 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023083 if(not $TargetSysInfo) {
23084 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
23085 }
23086
23087 if(not -d $TargetSysInfo) {
23088 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23089 }
23090
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023091 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023092 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023093 { # system XML descriptor
23094 if(not -f $DumpSystem) {
23095 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23096 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023097
23098 my $SDesc = readFile($DumpSystem);
23099 if(my $RelDir = $RelativeDirectory{1}) {
23100 $SDesc =~ s/{RELPATH}/$RelDir/g;
23101 }
23102
23103 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023104 foreach (@{$Ret->{"Tools"}})
23105 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023106 push_U($SystemPaths{"bin"}, $_);
23107 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023108 }
23109 if($Ret->{"CrossPrefix"}) {
23110 $CrossPrefix = $Ret->{"CrossPrefix"};
23111 }
23112 }
23113 elsif($SystemRoot_Opt)
23114 { # -sysroot "/" option
23115 # default target: /usr/lib, /usr/include
23116 # search libs: /usr/lib and /lib
23117 if(not -e $SystemRoot."/usr/lib") {
23118 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23119 }
23120 if(not -e $SystemRoot."/lib") {
23121 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23122 }
23123 if(not -e $SystemRoot."/usr/include") {
23124 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23125 }
23126 readSystemDescriptor("
23127 <name>
23128 $DumpSystem
23129 </name>
23130 <headers>
23131 $SystemRoot/usr/include
23132 </headers>
23133 <libs>
23134 $SystemRoot/usr/lib
23135 </libs>
23136 <search_libs>
23137 $SystemRoot/lib
23138 </search_libs>");
23139 }
23140 else {
23141 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23142 }
23143 detect_default_paths("bin|gcc"); # to check symbols
23144 if($OStarget eq "windows")
23145 { # to run dumpbin.exe
23146 # and undname.exe
23147 check_win32_env();
23148 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023149 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023150 exit(0);
23151 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023152
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023153 if($CmpSystems)
23154 { # --cmp-systems
23155 detect_default_paths("bin"); # to extract dumps
23156 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023157 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023158 exit(0);
23159 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023160
23161 if(not $CountSymbols)
23162 {
23163 if(not $TargetLibraryName) {
23164 exitStatus("Error", "library name is not selected (-l option)");
23165 }
23166 else
23167 { # validate library name
23168 if($TargetLibraryName=~/[\*\/\\]/) {
23169 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023171 }
23172 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023173
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023174 if(not $TargetTitle) {
23175 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023176 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023178 if($SymbolsListPath)
23179 {
23180 if(not -f $SymbolsListPath) {
23181 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23182 }
23183 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23184 $SymbolsList{$Interface} = 1;
23185 }
23186 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023187 if($TypesListPath)
23188 {
23189 if(not -f $TypesListPath) {
23190 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23191 }
23192 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23193 $TypesList{$Type} = 1;
23194 }
23195 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023196 if($SkipSymbolsListPath)
23197 {
23198 if(not -f $SkipSymbolsListPath) {
23199 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23200 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023201 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23202 {
23203 $SkipSymbols{1}{$Interface} = 1;
23204 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023205 }
23206 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023207 if($SkipTypesListPath)
23208 {
23209 if(not -f $SkipTypesListPath) {
23210 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23211 }
23212 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23213 {
23214 $SkipTypes{1}{$Type} = 1;
23215 $SkipTypes{2}{$Type} = 1;
23216 }
23217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023218 if($SkipHeadersPath)
23219 {
23220 if(not -f $SkipHeadersPath) {
23221 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23222 }
23223 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023224 { # register for both versions
23225 $SkipHeadersList{1}{$Path} = 1;
23226 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023228 my ($CPath, $Type) = classifyPath($Path);
23229 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023230 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023231 }
23232 }
23233 if($ParamNamesPath)
23234 {
23235 if(not -f $ParamNamesPath) {
23236 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23237 }
23238 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23239 {
23240 if($Line=~s/\A(\w+)\;//)
23241 {
23242 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023243 if($Line=~/;(\d+);/)
23244 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023245 while($Line=~s/(\d+);(\w+)//) {
23246 $AddIntParams{$Interface}{$1}=$2;
23247 }
23248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023249 else
23250 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023251 my $Num = 0;
23252 foreach my $Name (split(/;/, $Line)) {
23253 $AddIntParams{$Interface}{$Num++}=$Name;
23254 }
23255 }
23256 }
23257 }
23258 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023259
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023260 if($AppPath)
23261 {
23262 if(not -f $AppPath) {
23263 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23264 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023265
23266 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023267 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023268 $SymbolsList_App{$Interface} = 1;
23269 }
23270 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023271
23272 if($CountSymbols)
23273 {
23274 if(not -e $CountSymbols) {
23275 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23276 }
23277
23278 read_ABI_Dump(1, $CountSymbols);
23279
23280 foreach my $Id (keys(%{$SymbolInfo{1}}))
23281 {
23282 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23283 if(not $MnglName) {
23284 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23285 }
23286
23287 if(my $SV = $SymVer{1}{$MnglName}) {
23288 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23289 }
23290 else {
23291 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23292 }
23293
23294 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23295 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23296 }
23297 }
23298
23299 my $Count = 0;
23300 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23301 {
23302 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23303 next;
23304 }
23305 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23306 next;
23307 }
23308 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23309 next;
23310 }
23311
23312 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23313 }
23314
23315 printMsg("INFO", $Count);
23316 exit(0);
23317 }
23318
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023319 if($DumpAPI)
23320 { # --dump-abi
23321 # make an API dump
23322 create_ABI_Dump();
23323 exit($COMPILE_ERRORS);
23324 }
23325 # default: compare APIs
23326 # -d1 <path>
23327 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023328 compareInit();
23329 if($JoinReport or $DoubleReport)
23330 {
23331 compareAPIs("Binary");
23332 compareAPIs("Source");
23333 }
23334 elsif($BinaryOnly) {
23335 compareAPIs("Binary");
23336 }
23337 elsif($SourceOnly) {
23338 compareAPIs("Source");
23339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023340 exitReport();
23341}
23342
23343scenario();