blob: e71d93adacd4f74d90af4f526d5f17efa49919fa [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03003# ABI Compliance Checker (ABICC) 1.99.23
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 Ponomarenko81b09e82016-08-11 20:14:41 +030063my $TOOL_VERSION = "1.99.23";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040064my $ABI_DUMP_VERSION = "3.2";
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 Ponomarenko07aea072012-11-12 16:15:07 +040088$SkipHeadersPath, $CppCompat, $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 Ponomarenko1fbbce62015-10-13 00:08:59 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat,
93$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle,
95$DisableQuickEmptyReport);
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 Ponomarenko07aea072012-11-12 16:15:07 +0400231 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400232 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400233 "p|params=s" => \$ParamNamesPath,
234 "relpath1|relpath=s" => \$RelativeDirectory{1},
235 "relpath2=s" => \$RelativeDirectory{2},
236 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400237 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400239 "bin-report-path=s" => \$BinaryReportPath,
240 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400241 "log-path=s" => \$LoggingPath,
242 "log1-path=s" => \$OutputLogPath{1},
243 "log2-path=s" => \$OutputLogPath{2},
244 "logging-mode=s" => \$LogMode,
245 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300246 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400248 "extra-info=s" => \$ExtraInfo,
249 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400250 "force!" => \$Force,
251 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400252 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400253 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400254 "quick!" => \$Quick,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300255 "disable-quick-empty-report!" => \$DisableQuickEmptyReport,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400256 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300257 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
258 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300259 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400260) or ERR_MESSAGE();
261
262sub ERR_MESSAGE()
263{
264 printMsg("INFO", "\n".$ShortUsage);
265 exit($ERROR_CODE{"Error"});
266}
267
268my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
269my $SLIB_TYPE = $LIB_TYPE;
270if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
271{ # show as "shared" library
272 $SLIB_TYPE = "shared";
273}
274my $LIB_EXT = getLIB_EXT($OSgroup);
275my $AR_EXT = getAR_EXT($OSgroup);
276my $BYTE_SIZE = 8;
277my $COMMON_LOG_PATH = "logs/run.log";
278
279my $HelpMessage="
280NAME:
281 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400282 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400283
284DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400285 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400286 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
287 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
288 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
289 and/or source-level compatibility: changes in calling stack, v-table changes,
290 removed symbols, renamed fields, etc. Binary incompatibility may result in
291 crashing or incorrect behavior of applications built with an old version of
292 a library if they run on a new one. Source incompatibility may result in
293 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400294
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400295 The tool is intended for developers of software libraries and maintainers
296 of operating systems who are interested in ensuring backward compatibility,
297 i.e. allow old applications to run or to be recompiled with newer library
298 versions.
299
300 Also the tool can be used by ISVs for checking applications portability to
301 new library versions. Found issues can be taken into account when adapting
302 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400303
304 This tool is free software: you can redistribute it and/or modify it
305 under the terms of the GNU LGPL or GNU GPL.
306
307USAGE:
308 $CmdName [options]
309
310EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400311 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400312
313 OLD.xml and NEW.xml are XML-descriptors:
314
315 <version>
316 1.0
317 </version>
318
319 <headers>
320 /path1/to/header(s)/
321 /path2/to/header(s)/
322 ...
323 </headers>
324
325 <libs>
326 /path1/to/library(ies)/
327 /path2/to/library(ies)/
328 ...
329 </libs>
330
331INFORMATION OPTIONS:
332 -h|-help
333 Print this help.
334
335 -i|-info
336 Print complete info.
337
338 -v|-version
339 Print version information.
340
341 -dumpversion
342 Print the tool version ($TOOL_VERSION) and don't do anything else.
343
344GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400345 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400346 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400347
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400348 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400349 Descriptor of 1st (old) library version.
350 It may be one of the following:
351
352 1. XML-descriptor (VERSION.xml file):
353
354 <version>
355 1.0
356 </version>
357
358 <headers>
359 /path1/to/header(s)/
360 /path2/to/header(s)/
361 ...
362 </headers>
363
364 <libs>
365 /path1/to/library(ies)/
366 /path2/to/library(ies)/
367 ...
368 </libs>
369
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300370 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371
372 2. ABI dump generated by -dump option
373 3. Directory with headers and/or $SLIB_TYPE libraries
374 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400375
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300376 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400377 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400378
379 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400380 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400381
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400382 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400383 Descriptor of 2nd (new) library version.
384
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400385 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400386 Create library ABI dump for the input XML descriptor. You can
387 transfer it anywhere and pass instead of the descriptor. Also
388 it can be used for debugging the tool.
389
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300390 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400391
392sub HELP_MESSAGE() {
393 printMsg("INFO", $HelpMessage."
394MORE INFO:
395 $CmdName --info\n");
396}
397
398sub INFO_MESSAGE()
399{
400 printMsg("INFO", "$HelpMessage
401EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400402 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300403 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400404 for portability to the new library version.
405
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300406 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 Check static libraries instead of the shared ones. The <libs> section
408 of the XML-descriptor should point to static libraries location.
409
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300410 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400411 Path to the cross GCC compiler to use instead of the usual (host) GCC.
412
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300413 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300415
416 -gcc-options OPTS
417 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400420 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400421 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400423 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400424 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200425 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400426
427 In general case you should specify it in the XML-descriptor:
428 <version>
429 VERSION
430 </version>
431
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400432 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400433 Specify 2nd library version outside the descriptor.
434
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400435 -vnum NUM
436 Specify the library version in the generated ABI dump. The <version> section
437 of the input XML descriptor will be overwritten in this case.
438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400439 -s|-strict
440 Treat all compatibility warnings as problems. Add a number of \"Low\"
441 severity problems to the return value of the tool.
442
443 -headers-only
444 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
445 provide a low quality compatibility report with false positives and
446 without detecting of added/removed symbols.
447
448 Alternatively you can write \"none\" word to the <libs> section
449 in the XML-descriptor:
450 <libs>
451 none
452 </libs>
453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400454 -show-retval
455 Show the symbol's return type in the report.
456
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400457 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300458 This option allows to specify a file with a list of symbols (mangled
459 names in C++) that should be checked. Other symbols will not be checked.
460
461 -types-list PATH
462 This option allows to specify a file with a list of types that should
463 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400464
465 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300466 The list of symbols that should not be checked.
467
468 -skip-types PATH
469 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400470
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400471 -headers-list PATH
472 The file with a list of headers, that should be checked/dumped.
473
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400474 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400475 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400476
477 -header NAME
478 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400479
480 -use-dumps
481 Make dumps for two versions of a library and compare dumps. This should
482 increase the performance of the tool and decrease the system memory usage.
483
484 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400485 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400486
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400487 -dump-system NAME -sysroot DIR
488 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400489 create XML descriptors and make ABI dumps for each library. The result
490 set of ABI dumps can be compared (--cmp-systems) with the other one
491 created for other version of operating system in order to check them for
492 compatibility. Do not forget to specify -cross-gcc option if your target
493 system requires some specific version of GCC compiler (different from
494 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400495 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400496
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400497 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400498 The same as the previous option but takes an XML descriptor of the target
499 system as input, where you should describe it:
500
501 /* Primary sections */
502
503 <name>
504 /* Name of the system */
505 </name>
506
507 <headers>
508 /* The list of paths to header files and/or
509 directories with header files, one per line */
510 </headers>
511
512 <libs>
513 /* The list of paths to shared libraries and/or
514 directories with shared libraries, one per line */
515 </libs>
516
517 /* Optional sections */
518
519 <search_headers>
520 /* List of directories to be searched
521 for header files to automatically
522 generate include paths, one per line */
523 </search_headers>
524
525 <search_libs>
526 /* List of directories to be searched
527 for shared libraries to resolve
528 dependencies, one per line */
529 </search_libs>
530
531 <tools>
532 /* List of directories with tools used
533 for analysis (GCC toolchain), one per line */
534 </tools>
535
536 <cross_prefix>
537 /* GCC toolchain prefix.
538 Examples:
539 arm-linux-gnueabi
540 arm-none-symbianelf */
541 </cross_prefix>
542
543 <gcc_options>
544 /* Additional GCC options, one per line */
545 </gcc_options>
546
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400547 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300548 This option should be used with -dump-system option to dump
549 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400550
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400551 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400552 Compare two system ABI dumps. Create compatibility reports for each
553 library and the common HTML report including the summary of test
554 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400555 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400556
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400557 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400558 The file with a list of libraries, that should be dumped by
559 the -dump-system option or should be checked by the -cmp-systems option.
560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400561 -ext|-extended
562 If your library A is supposed to be used by other library B and you
563 want to control the ABI of B, then you should enable this option. The
564 tool will check for changes in all data types, even if they are not
565 used by any function in the library A. Such data types are not part
566 of the A library ABI, but may be a part of the ABI of the B library.
567
568 The short scheme is:
569 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
570
571 -q|-quiet
572 Print all messages to the file instead of stdout and stderr.
573 Default path (can be changed by -log-path option):
574 $COMMON_LOG_PATH
575
576 -stdout
577 Print analysis results (compatibility reports and ABI dumps) to stdout
578 instead of creating a file. This would allow piping data to other programs.
579
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400580 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400581 Change format of compatibility report.
582 Formats:
583 htm - HTML format (default)
584 xml - XML format
585
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400586 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400587 Change format of ABI dump.
588 Formats:
589 perl - Data::Dumper format (default)
590 xml - XML format
591
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400592 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400593 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400594
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400595 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596 Set library language (C or C++). You can use this option if the tool
597 cannot auto-detect a language. This option may be useful for checking
598 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400599
600 -arch ARCH
601 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
602 ect.). The option is useful if the tool cannot detect correct architecture
603 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400604
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400605 -binary|-bin|-abi
606 Show \"Binary\" compatibility problems only.
607 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400608 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400609
610 -source|-src|-api
611 Show \"Source\" compatibility problems only.
612 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400613 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400614
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400615 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400616 The maximum number of affected symbols listed under the description
617 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300618
619 -count-symbols PATH
620 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300621
622 -old-style
623 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400625OTHER OPTIONS:
626 -test
627 Run internal tests. Create two binary incompatible versions of a sample
628 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300629 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400630
631 -test-dump
632 Test ability to create, read and compare ABI dumps.
633
634 -debug
635 Debugging mode. Print debug info on the screen. Save intermediate
636 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400637 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400638
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400639 Also consider using --dump option for debugging the tool.
640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400641 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400642 If your header files are written in C language and can be compiled
643 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
644 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400645
646 -cpp-incompatible
647 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400648
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400649 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400650 Path to file with the function parameter names. It can be used
651 for improving report view if the library header files have no
652 parameter names. File format:
653
654 func1;param1;param2;param3 ...
655 func2;param1;param2;param3 ...
656 ...
657
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400658 -relpath PATH
659 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400660 for dumping the library ABI (see -dump option).
661
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 -relpath1 PATH
663 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400664
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400665 -relpath2 PATH
666 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400667
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400669 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400670 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400672
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400673 -sort
674 Enable sorting of data in ABI dumps.
675
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400676 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400677 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400678 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400679 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400682 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400685
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400687 Path to \"Source\" compatibility report.
688 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 Log path for all messages.
693 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697 Log path for 1st version of a library.
698 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400700
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400701 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400702 Log path for 2nd version of a library.
703 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400705
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400706 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400707 Change logging mode.
708 Modes:
709 w - overwrite old logs (default)
710 a - append old logs
711 n - do not write any logs
712
713 -list-affected
714 Generate file with the list of incompatible
715 symbols beside the HTML compatibility report.
716 Use 'c++filt \@file' command from GNU binutils
717 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400718 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400720 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400723 The component name in the title and summary of the HTML report.
724 Default:
725 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300726
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300727 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730
731 -extra-info DIR
732 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400733
734 -extra-dump
735 Create extended ABI dump containing all symbols
736 from the translation unit.
737
738 -force
739 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400740
741 -tolerance LEVEL
742 Apply a set of heuristics to successfully compile input
743 header files. You can enable several tolerance levels by
744 joining them into one string (e.g. 13, 124, etc.).
745 Levels:
746 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
747 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900748 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400749 4 - skip headers included by others
750
751 -tolerant
752 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400753
754 -check
755 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400756
757 -quick
758 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300759
760 -disable-quick-empty-report
761 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400762
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300763 -skip-internal-symbols PATTERN
764 Do not check symbols matched by the pattern.
765
766 -skip-internal-types PATTERN
767 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300768
769 -check-private-abi
770 Check data types from the private part of the ABI when
771 comparing ABI dumps created by the ABI Dumper tool with
772 use of the -public-headers option.
773
774 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400775
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400776REPORT:
777 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400778 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400779
780 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400781 logs/LIB_NAME/V1/log.txt
782 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400783
784EXIT CODES:
785 0 - Compatible. The tool has run without any errors.
786 non-zero - Incompatible or the tool has run with errors.
787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400788MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300789 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400790}
791
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400792my %Operator_Indication = (
793 "not" => "~",
794 "assign" => "=",
795 "andassign" => "&=",
796 "orassign" => "|=",
797 "xorassign" => "^=",
798 "or" => "|",
799 "xor" => "^",
800 "addr" => "&",
801 "and" => "&",
802 "lnot" => "!",
803 "eq" => "==",
804 "ne" => "!=",
805 "lt" => "<",
806 "lshift" => "<<",
807 "lshiftassign" => "<<=",
808 "rshiftassign" => ">>=",
809 "call" => "()",
810 "mod" => "%",
811 "modassign" => "%=",
812 "subs" => "[]",
813 "land" => "&&",
814 "lor" => "||",
815 "rshift" => ">>",
816 "ref" => "->",
817 "le" => "<=",
818 "deref" => "*",
819 "mult" => "*",
820 "preinc" => "++",
821 "delete" => " delete",
822 "vecnew" => " new[]",
823 "vecdelete" => " delete[]",
824 "predec" => "--",
825 "postinc" => "++",
826 "postdec" => "--",
827 "plusassign" => "+=",
828 "plus" => "+",
829 "minus" => "-",
830 "minusassign" => "-=",
831 "gt" => ">",
832 "ge" => ">=",
833 "new" => " new",
834 "multassign" => "*=",
835 "divassign" => "/=",
836 "div" => "/",
837 "neg" => "-",
838 "pos" => "+",
839 "memref" => "->*",
840 "compound" => "," );
841
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400842my %UnknownOperator;
843
844my %NodeType= (
845 "array_type" => "Array",
846 "binfo" => "Other",
847 "boolean_type" => "Intrinsic",
848 "complex_type" => "Intrinsic",
849 "const_decl" => "Other",
850 "enumeral_type" => "Enum",
851 "field_decl" => "Other",
852 "function_decl" => "Other",
853 "function_type" => "FunctionType",
854 "identifier_node" => "Other",
855 "integer_cst" => "Other",
856 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400857 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400858 "method_type" => "MethodType",
859 "namespace_decl" => "Other",
860 "parm_decl" => "Other",
861 "pointer_type" => "Pointer",
862 "real_cst" => "Other",
863 "real_type" => "Intrinsic",
864 "record_type" => "Struct",
865 "reference_type" => "Ref",
866 "string_cst" => "Other",
867 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400868 "template_type_parm" => "TemplateParam",
869 "typename_type" => "TypeName",
870 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400871 "tree_list" => "Other",
872 "tree_vec" => "Other",
873 "type_decl" => "Other",
874 "union_type" => "Union",
875 "var_decl" => "Other",
876 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400877 "nop_expr" => "Other", #
878 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400879 "offset_type" => "Other" );
880
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400881my %CppKeywords_C = map {$_=>1} (
882 # C++ 2003 keywords
883 "public",
884 "protected",
885 "private",
886 "default",
887 "template",
888 "new",
889 #"asm",
890 "dynamic_cast",
891 "auto",
892 "try",
893 "namespace",
894 "typename",
895 "using",
896 "reinterpret_cast",
897 "friend",
898 "class",
899 "virtual",
900 "const_cast",
901 "mutable",
902 "static_cast",
903 "export",
904 # C++0x keywords
905 "noexcept",
906 "nullptr",
907 "constexpr",
908 "static_assert",
909 "explicit",
910 # cannot be used as a macro name
911 # as it is an operator in C++
912 "and",
913 #"and_eq",
914 "not",
915 #"not_eq",
916 "or"
917 #"or_eq",
918 #"bitand",
919 #"bitor",
920 #"xor",
921 #"xor_eq",
922 #"compl"
923);
924
925my %CppKeywords_F = map {$_=>1} (
926 "delete",
927 "catch",
928 "alignof",
929 "thread_local",
930 "decltype",
931 "typeid"
932);
933
934my %CppKeywords_O = map {$_=>1} (
935 "bool",
936 "register",
937 "inline",
938 "operator"
939);
940
941my %CppKeywords_A = map {$_=>1} (
942 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400943 "throw",
944 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400945);
946
947foreach (keys(%CppKeywords_C),
948keys(%CppKeywords_F),
949keys(%CppKeywords_O)) {
950 $CppKeywords_A{$_}=1;
951}
952
953# Header file extensions as described by gcc
954my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
955
956my %IntrinsicMangling = (
957 "void" => "v",
958 "bool" => "b",
959 "wchar_t" => "w",
960 "char" => "c",
961 "signed char" => "a",
962 "unsigned char" => "h",
963 "short" => "s",
964 "unsigned short" => "t",
965 "int" => "i",
966 "unsigned int" => "j",
967 "long" => "l",
968 "unsigned long" => "m",
969 "long long" => "x",
970 "__int64" => "x",
971 "unsigned long long" => "y",
972 "__int128" => "n",
973 "unsigned __int128" => "o",
974 "float" => "f",
975 "double" => "d",
976 "long double" => "e",
977 "__float80" => "e",
978 "__float128" => "g",
979 "..." => "z"
980);
981
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400982my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
983
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400984my %StdcxxMangling = (
985 "3std"=>"St",
986 "3std9allocator"=>"Sa",
987 "3std12basic_string"=>"Sb",
988 "3std12basic_stringIcE"=>"Ss",
989 "3std13basic_istreamIcE"=>"Si",
990 "3std13basic_ostreamIcE"=>"So",
991 "3std14basic_iostreamIcE"=>"Sd"
992);
993
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400994my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400995my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
996
997my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400998my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001000my %ConstantSuffix = (
1001 "unsigned int"=>"u",
1002 "long"=>"l",
1003 "unsigned long"=>"ul",
1004 "long long"=>"ll",
1005 "unsigned long long"=>"ull"
1006);
1007
1008my %ConstantSuffixR =
1009reverse(%ConstantSuffix);
1010
1011my %OperatorMangling = (
1012 "~" => "co",
1013 "=" => "aS",
1014 "|" => "or",
1015 "^" => "eo",
1016 "&" => "an",#ad (addr)
1017 "==" => "eq",
1018 "!" => "nt",
1019 "!=" => "ne",
1020 "<" => "lt",
1021 "<=" => "le",
1022 "<<" => "ls",
1023 "<<=" => "lS",
1024 ">" => "gt",
1025 ">=" => "ge",
1026 ">>" => "rs",
1027 ">>=" => "rS",
1028 "()" => "cl",
1029 "%" => "rm",
1030 "[]" => "ix",
1031 "&&" => "aa",
1032 "||" => "oo",
1033 "*" => "ml",#de (deref)
1034 "++" => "pp",#
1035 "--" => "mm",#
1036 "new" => "nw",
1037 "delete" => "dl",
1038 "new[]" => "na",
1039 "delete[]" => "da",
1040 "+=" => "pL",
1041 "+" => "pl",#ps (pos)
1042 "-" => "mi",#ng (neg)
1043 "-=" => "mI",
1044 "*=" => "mL",
1045 "/=" => "dV",
1046 "&=" => "aN",
1047 "|=" => "oR",
1048 "%=" => "rM",
1049 "^=" => "eO",
1050 "/" => "dv",
1051 "->*" => "pm",
1052 "->" => "pt",#rf (ref)
1053 "," => "cm",
1054 "?" => "qu",
1055 "." => "dt",
1056 "sizeof"=> "sz"#st
1057);
1058
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001059my %Intrinsic_Keywords = map {$_=>1} (
1060 "true",
1061 "false",
1062 "_Bool",
1063 "_Complex",
1064 "const",
1065 "int",
1066 "long",
1067 "void",
1068 "short",
1069 "float",
1070 "volatile",
1071 "restrict",
1072 "unsigned",
1073 "signed",
1074 "char",
1075 "double",
1076 "class",
1077 "struct",
1078 "union",
1079 "enum"
1080);
1081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001082my %GlibcHeader = map {$_=>1} (
1083 "aliases.h",
1084 "argp.h",
1085 "argz.h",
1086 "assert.h",
1087 "cpio.h",
1088 "ctype.h",
1089 "dirent.h",
1090 "envz.h",
1091 "errno.h",
1092 "error.h",
1093 "execinfo.h",
1094 "fcntl.h",
1095 "fstab.h",
1096 "ftw.h",
1097 "glob.h",
1098 "grp.h",
1099 "iconv.h",
1100 "ifaddrs.h",
1101 "inttypes.h",
1102 "langinfo.h",
1103 "limits.h",
1104 "link.h",
1105 "locale.h",
1106 "malloc.h",
1107 "math.h",
1108 "mntent.h",
1109 "monetary.h",
1110 "nl_types.h",
1111 "obstack.h",
1112 "printf.h",
1113 "pwd.h",
1114 "regex.h",
1115 "sched.h",
1116 "search.h",
1117 "setjmp.h",
1118 "shadow.h",
1119 "signal.h",
1120 "spawn.h",
1121 "stdarg.h",
1122 "stdint.h",
1123 "stdio.h",
1124 "stdlib.h",
1125 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001126 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001127 "tar.h",
1128 "termios.h",
1129 "time.h",
1130 "ulimit.h",
1131 "unistd.h",
1132 "utime.h",
1133 "wchar.h",
1134 "wctype.h",
1135 "wordexp.h" );
1136
1137my %GlibcDir = map {$_=>1} (
1138 "arpa",
1139 "bits",
1140 "gnu",
1141 "netinet",
1142 "net",
1143 "nfs",
1144 "rpc",
1145 "sys",
1146 "linux" );
1147
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001148my %WinHeaders = map {$_=>1} (
1149 "dos.h",
1150 "process.h",
1151 "winsock.h",
1152 "config-win.h",
1153 "mem.h",
1154 "windows.h",
1155 "winsock2.h",
1156 "crtdbg.h",
1157 "ws2tcpip.h"
1158);
1159
1160my %ObsoleteHeaders = map {$_=>1} (
1161 "iostream.h",
1162 "fstream.h"
1163);
1164
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001165my %AlienHeaders = map {$_=>1} (
1166 # Solaris
1167 "thread.h",
1168 "sys/atomic.h",
1169 # HPUX
1170 "sys/stream.h",
1171 # Symbian
1172 "AknDoc.h",
1173 # Atari ST
1174 "ext.h",
1175 "tos.h",
1176 # MS-DOS
1177 "alloc.h",
1178 # Sparc
1179 "sys/atomic.h"
1180);
1181
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001182my %ConfHeaders = map {$_=>1} (
1183 "atomic",
1184 "conf.h",
1185 "config.h",
1186 "configure.h",
1187 "build.h",
1188 "setup.h"
1189);
1190
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001191my %LocalIncludes = map {$_=>1} (
1192 "/usr/local/include",
1193 "/usr/local" );
1194
1195my %OS_AddPath=(
1196# These paths are needed if the tool cannot detect them automatically
1197 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001198 "include"=>[
1199 "/Library",
1200 "/Developer/usr/include"
1201 ],
1202 "lib"=>[
1203 "/Library",
1204 "/Developer/usr/lib"
1205 ],
1206 "bin"=>[
1207 "/Developer/usr/bin"
1208 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001209 },
1210 "beos"=>{
1211 # Haiku has GCC 2.95.3 by default
1212 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001213 "include"=>[
1214 "/boot/common",
1215 "/boot/develop"
1216 ],
1217 "lib"=>[
1218 "/boot/common/lib",
1219 "/boot/system/lib",
1220 "/boot/apps"
1221 ],
1222 "bin"=>[
1223 "/boot/common/bin",
1224 "/boot/system/bin",
1225 "/boot/develop/abi"
1226 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001228);
1229
1230my %Slash_Type=(
1231 "default"=>"/",
1232 "windows"=>"\\"
1233);
1234
1235my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1236
1237# Global Variables
1238my %COMMON_LANGUAGE=(
1239 1 => "C",
1240 2 => "C" );
1241
1242my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001243my $MAX_CPPFILT_FILE_SIZE = 50000;
1244my $CPPFILT_SUPPORT_FILE;
1245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001246my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1247
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001248my $STDCXX_TESTING = 0;
1249my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001250my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001251
1252my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001253my $CheckUndefined = 0;
1254
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001255my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001256if($TargetComponent_Opt) {
1257 $TargetComponent = lc($TargetComponent_Opt);
1258}
1259else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001260{ # default: library
1261 # other components: header, system, ...
1262 $TargetComponent = "library";
1263}
1264
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001265my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001267my $SystemRoot;
1268
1269my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001270my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001271my %LOG_PATH;
1272my %DEBUG_PATH;
1273my %Cache;
1274my %LibInfo;
1275my $COMPILE_ERRORS = 0;
1276my %CompilerOptions;
1277my %CheckedDyLib;
1278my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1279
1280# Constants (#defines)
1281my %Constants;
1282my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001283my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001284
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001285# Extra Info
1286my %SymbolHeader;
1287my %KnownLibs;
1288
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001289# Templates
1290my %TemplateInstance;
1291my %BasicTemplate;
1292my %TemplateArg;
1293my %TemplateDecl;
1294my %TemplateMap;
1295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296# Types
1297my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298my %SkipTypes = (
1299 "1"=>{},
1300 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001301my %CheckedTypes;
1302my %TName_Tid;
1303my %EnumMembName_Id;
1304my %NestedNameSpaces = (
1305 "1"=>{},
1306 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001308my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001309my %ClassVTable;
1310my %ClassVTable_Content;
1311my %VTableClass;
1312my %AllocableClass;
1313my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001314my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001315my %Class_SubClasses;
1316my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001317my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001318my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001319
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001320my %CheckedTypeInfo;
1321
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001322# Typedefs
1323my %Typedef_BaseName;
1324my %Typedef_Tr;
1325my %Typedef_Eq;
1326my %StdCxxTypedef;
1327my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001328my %MissedBase;
1329my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001330my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331
1332# Symbols
1333my %SymbolInfo;
1334my %tr_name;
1335my %mangled_name_gcc;
1336my %mangled_name;
1337my %SkipSymbols = (
1338 "1"=>{},
1339 "2"=>{} );
1340my %SkipNameSpaces = (
1341 "1"=>{},
1342 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001343my %AddNameSpaces = (
1344 "1"=>{},
1345 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001346my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001347my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001348my %SymbolsList_App;
1349my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001350my %Symbol_Library = (
1351 "1"=>{},
1352 "2"=>{} );
1353my %Library_Symbol = (
1354 "1"=>{},
1355 "2"=>{} );
1356my %DepSymbol_Library = (
1357 "1"=>{},
1358 "2"=>{} );
1359my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001360 "1"=>{},
1361 "2"=>{} );
1362my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001363my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001364my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001365my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001366my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001367my %Library_Needed= (
1368 "1"=>{},
1369 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001370
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001371# Extra Info
1372my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001373my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001375# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001376my %Include_Preamble = (
1377 "1"=>[],
1378 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001379my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001380my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001381my %HeaderName_Paths;
1382my %Header_Dependency;
1383my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001384my %Include_Paths = (
1385 "1"=>[],
1386 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387my %INC_PATH_AUTODETECT = (
1388 "1"=>1,
1389 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001390my %Add_Include_Paths = (
1391 "1"=>[],
1392 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001393my %Skip_Include_Paths;
1394my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001395my %Header_ErrorRedirect;
1396my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001397my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398my %Header_ShouldNotBeUsed;
1399my %RecursiveIncludes;
1400my %Header_Include_Prefix;
1401my %SkipHeaders;
1402my %SkipHeadersList=(
1403 "1"=>{},
1404 "2"=>{} );
1405my %SkipLibs;
1406my %Include_Order;
1407my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001408my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001409my %TUnit_Funcs;
1410my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001412my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413 "1"=>0,
1414 "2"=>0 );
1415my %AutoPreambleMode = (
1416 "1"=>0,
1417 "2"=>0 );
1418my %MinGWMode = (
1419 "1"=>0,
1420 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001421my %Cpp0xMode = (
1422 "1"=>0,
1423 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424
1425# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001426my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001427my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001428my %RegisteredSONAMEs;
1429my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001430
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001431my %CheckedArch;
1432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001433# System Objects
1434my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001435my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001436my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001437
1438# System Headers
1439my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001440my @DefaultCppPaths;
1441my @DefaultGccPaths;
1442my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001443my %DefaultCppHeader;
1444my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001445my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446
1447# Merging
1448my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001449my $Version;
1450my %AddedInt;
1451my %RemovedInt;
1452my %AddedInt_Virt;
1453my %RemovedInt_Virt;
1454my %VirtualReplacement;
1455my %ChangedTypedef;
1456my %CompatRules;
1457my %IncompleteRules;
1458my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001459my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001460my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461my %ReturnedClass;
1462my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001463my %SourceAlternative;
1464my %SourceAlternative_B;
1465my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001466my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001468#Report
1469my %TypeChanges;
1470
1471#Speedup
1472my %TypeProblemsIndex;
1473
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001474# Calling Conventions
1475my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001476 1=>{ "R"=>0, "P"=>0 },
1477 2=>{ "R"=>0, "P"=>0 }
1478);
1479
1480# ABI Dump
1481my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001482
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001483# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my %TargetLibs;
1485my %TargetHeaders;
1486
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001487# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001488my $OStarget = $OSgroup;
1489my %TargetTools;
1490
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491# Recursion locks
1492my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001493my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001494my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001495my @RecurInclude;
1496my @RecurConstant;
1497
1498# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001499my %SystemPaths = (
1500 "include"=>[],
1501 "lib"=>[],
1502 "bin"=>[]
1503);
1504my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001505my $GCC_PATH;
1506
1507# Symbols versioning
1508my %SymVer = (
1509 "1"=>{},
1510 "2"=>{} );
1511
1512# Problem descriptions
1513my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001514my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001515my %TotalAffected;
1516
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001517# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001518my $ContentID = 1;
1519my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001520my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1521my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001522my $ContentSpanEnd = "</span>\n";
1523my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1524my $ContentDivEnd = "</div>\n";
1525my $Content_Counter = 0;
1526
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001527# Modes
1528my $JoinReport = 1;
1529my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001530
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001531my %Severity_Val=(
1532 "High"=>3,
1533 "Medium"=>2,
1534 "Low"=>1,
1535 "Safe"=>-1
1536);
1537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538sub get_Modules()
1539{
1540 my $TOOL_DIR = get_dirname($0);
1541 if(not $TOOL_DIR)
1542 { # patch for MS Windows
1543 $TOOL_DIR = ".";
1544 }
1545 my @SEARCH_DIRS = (
1546 # tool's directory
1547 abs_path($TOOL_DIR),
1548 # relative path to modules
1549 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001550 # install path
1551 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552 );
1553 foreach my $DIR (@SEARCH_DIRS)
1554 {
1555 if(not is_abs($DIR))
1556 { # relative path
1557 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1558 }
1559 if(-d $DIR."/modules") {
1560 return $DIR."/modules";
1561 }
1562 }
1563 exitStatus("Module_Error", "can't find modules");
1564}
1565
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001566my %LoadedModules = ();
1567
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001568sub loadModule($)
1569{
1570 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001571 if(defined $LoadedModules{$Name}) {
1572 return;
1573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001574 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1575 if(not -f $Path) {
1576 exitStatus("Module_Error", "can't access \'$Path\'");
1577 }
1578 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001579 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001580}
1581
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001582sub readModule($$)
1583{
1584 my ($Module, $Name) = @_;
1585 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1586 if(not -f $Path) {
1587 exitStatus("Module_Error", "can't access \'$Path\'");
1588 }
1589 return readFile($Path);
1590}
1591
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001592sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001593{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001594 my $Number = $_[0];
1595 if(not $Number) {
1596 $Number = 1;
1597 }
1598 else {
1599 $Number = int($Number)+1;
1600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001601 if($Number>3) {
1602 return $Number."th";
1603 }
1604 elsif($Number==1) {
1605 return "1st";
1606 }
1607 elsif($Number==2) {
1608 return "2nd";
1609 }
1610 elsif($Number==3) {
1611 return "3rd";
1612 }
1613 else {
1614 return $Number;
1615 }
1616}
1617
1618sub search_Tools($)
1619{
1620 my $Name = $_[0];
1621 return "" if(not $Name);
1622 if(my @Paths = keys(%TargetTools))
1623 {
1624 foreach my $Path (@Paths)
1625 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001626 if(-f join_P($Path, $Name)) {
1627 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001628 }
1629 if($CrossPrefix)
1630 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001631 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001632 if(-f $Candidate) {
1633 return $Candidate;
1634 }
1635 }
1636 }
1637 }
1638 else {
1639 return "";
1640 }
1641}
1642
1643sub synch_Cmd($)
1644{
1645 my $Name = $_[0];
1646 if(not $GCC_PATH)
1647 { # GCC was not found yet
1648 return "";
1649 }
1650 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001651 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001652 return $Candidate;
1653 }
1654 return "";
1655}
1656
1657sub get_CmdPath($)
1658{
1659 my $Name = $_[0];
1660 return "" if(not $Name);
1661 if(defined $Cache{"get_CmdPath"}{$Name}) {
1662 return $Cache{"get_CmdPath"}{$Name};
1663 }
1664 my %BinUtils = map {$_=>1} (
1665 "c++filt",
1666 "objdump",
1667 "readelf"
1668 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001669 if($BinUtils{$Name} and $GCC_PATH)
1670 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001671 if(my $Dir = get_dirname($GCC_PATH)) {
1672 $TargetTools{$Dir}=1;
1673 }
1674 }
1675 my $Path = search_Tools($Name);
1676 if(not $Path and $OSgroup eq "windows") {
1677 $Path = search_Tools($Name.".exe");
1678 }
1679 if(not $Path and $BinUtils{$Name})
1680 {
1681 if($CrossPrefix)
1682 { # user-defined prefix
1683 $Path = search_Cmd($CrossPrefix."-".$Name);
1684 }
1685 }
1686 if(not $Path and $BinUtils{$Name})
1687 {
1688 if(my $Candidate = synch_Cmd($Name))
1689 { # synch with GCC
1690 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001691 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001692 if(-f $Candidate) {
1693 $Path = $Candidate;
1694 }
1695 }
1696 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001697 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001698 $Path = $Candidate;
1699 }
1700 }
1701 }
1702 if(not $Path) {
1703 $Path = search_Cmd($Name);
1704 }
1705 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001706 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001707 $Path=search_Cmd($Name.".exe");
1708 }
1709 if($Path=~/\s/) {
1710 $Path = "\"".$Path."\"";
1711 }
1712 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1713}
1714
1715sub search_Cmd($)
1716{
1717 my $Name = $_[0];
1718 return "" if(not $Name);
1719 if(defined $Cache{"search_Cmd"}{$Name}) {
1720 return $Cache{"search_Cmd"}{$Name};
1721 }
1722 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1723 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1724 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001725 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001726 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001727 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001728 if(-f $CmdPath)
1729 {
1730 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001731 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001732 }
1733 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1734 }
1735 }
1736 return ($Cache{"search_Cmd"}{$Name} = "");
1737}
1738
1739sub get_CmdPath_Default($)
1740{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001741 return "" if(not $_[0]);
1742 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1743 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001745 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1746}
1747
1748sub get_CmdPath_Default_I($)
1749{ # search in PATH
1750 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001751 if($Name=~/find/)
1752 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001753 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001754 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001755 }
1756 }
1757 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001758 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001759 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001760 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001761 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001762 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001763 if($OSgroup eq "windows")
1764 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001765 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001766 return $Name;
1767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001768 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001769 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001770 {
1771 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001772 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001773 }
1774 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001775 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001776}
1777
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001778sub classifyPath($)
1779{
1780 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001781 if($Path=~/[\*\+\(\[\|]/)
1782 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001783 return ($Path, "Pattern");
1784 }
1785 elsif($Path=~/[\/\\]/)
1786 { # directory or relative path
1787 return (path_format($Path, $OSgroup), "Path");
1788 }
1789 else {
1790 return ($Path, "Name");
1791 }
1792}
1793
1794sub readDescriptor($$)
1795{
1796 my ($LibVersion, $Content) = @_;
1797 return if(not $LibVersion);
1798 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1799 if(not $Content) {
1800 exitStatus("Error", "$DName is empty");
1801 }
1802 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001803 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001804 }
1805 $Content=~s/\/\*(.|\n)+?\*\///g;
1806 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001807
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001808 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1809 if($TargetVersion{$LibVersion}) {
1810 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1811 }
1812 if(not $Descriptor{$LibVersion}{"Version"}) {
1813 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1814 }
1815 if($Content=~/{RELPATH}/)
1816 {
1817 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1818 $Content =~ s/{RELPATH}/$RelDir/g;
1819 }
1820 else
1821 {
1822 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1823 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1824 }
1825 }
1826
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001827 my $DHeaders = parseTag(\$Content, "headers");
1828 if(not $DHeaders) {
1829 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1830 }
1831 elsif(lc($DHeaders) ne "none")
1832 { # append the descriptor headers list
1833 if($Descriptor{$LibVersion}{"Headers"})
1834 { # multiple descriptors
1835 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001836 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001837 else {
1838 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1839 }
1840 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1841 {
1842 if(not -e $Path) {
1843 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001844 }
1845 }
1846 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001847
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001848 if(not $CheckHeadersOnly_Opt)
1849 {
1850 my $DObjects = parseTag(\$Content, "libs");
1851 if(not $DObjects) {
1852 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1853 }
1854 elsif(lc($DObjects) ne "none")
1855 { # append the descriptor libraries list
1856 if($Descriptor{$LibVersion}{"Libs"})
1857 { # multiple descriptors
1858 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1859 }
1860 else {
1861 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1862 }
1863 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1864 {
1865 if(not -e $Path) {
1866 exitStatus("Access_Error", "can't access \'$Path\'");
1867 }
1868 }
1869 }
1870 }
1871 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1872 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001873 if(not -d $Path) {
1874 exitStatus("Access_Error", "can't access directory \'$Path\'");
1875 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001876 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001878 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 }
1880 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1881 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001882 if(not -d $Path) {
1883 exitStatus("Access_Error", "can't access directory \'$Path\'");
1884 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001885 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001886 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001887 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001888 }
1889 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1890 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001891 if(not -d $Path) {
1892 exitStatus("Access_Error", "can't access directory \'$Path\'");
1893 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001894 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001895 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001896 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 $TargetTools{$Path}=1;
1898 }
1899 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1900 $CrossPrefix = $Prefix;
1901 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001902 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1904 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 if(not -d $Path) {
1906 exitStatus("Access_Error", "can't access directory \'$Path\'");
1907 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001908 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001910 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001912 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001913 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1914 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001915 if(not -d $Path) {
1916 exitStatus("Access_Error", "can't access directory \'$Path\'");
1917 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001918 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001920 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001921 }
1922 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001923 { # skip some auto-generated include paths
1924 if(not is_abs($Path))
1925 {
1926 if(my $P = abs_path($Path)) {
1927 $Path = $P;
1928 }
1929 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001930 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001931 }
1932 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001933 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001934 my ($CPath, $Type) = classifyPath($Path);
1935 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 }
1937 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001938 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1939 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001940 if($Option!~/\A\-(Wl|l|L)/)
1941 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001942 $CompilerOptions{$LibVersion} .= " ".$Option;
1943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 }
1945 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1946 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1947 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001948 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001949
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001950 my ($CPath, $Type) = classifyPath($Path);
1951 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 }
1953 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1954 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1955 {
1956 my ($CPath, $Type) = classifyPath($Path);
1957 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1958 }
1959 if(my $DDefines = parseTag(\$Content, "defines"))
1960 {
1961 if($Descriptor{$LibVersion}{"Defines"})
1962 { # multiple descriptors
1963 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1964 }
1965 else {
1966 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1967 }
1968 }
1969 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1970 {
1971 if($Order=~/\A(.+):(.+)\Z/) {
1972 $Include_Order{$LibVersion}{$1} = $2;
1973 }
1974 }
1975 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1976 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001977 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001978 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1979 }
1980 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1981 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001982 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001983 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1984 }
1985 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1986 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1987 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001988 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1989 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001991 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1992 $SkipConstants{$LibVersion}{$Constant} = 1;
1993 }
1994 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1995 {
1996 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001997 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001998 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1999 }
2000 else {
2001 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2002 }
2003 }
2004}
2005
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002006sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002007{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002008 my $CodeRef = shift(@_);
2009 my $Tag = shift(@_);
2010 if(not $Tag or not $CodeRef) {
2011 return undef;
2012 }
2013 my $Sp = 0;
2014 if(@_) {
2015 $Sp = shift(@_);
2016 }
2017 my $Start = index(${$CodeRef}, "<$Tag>");
2018 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002019 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002020 my $End = index(${$CodeRef}, "</$Tag>");
2021 if($End!=-1)
2022 {
2023 my $TS = length($Tag)+3;
2024 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2025 substr($Content, 0, $TS-1, ""); # cut start tag
2026 substr($Content, -$TS, $TS, ""); # cut end tag
2027 if(not $Sp)
2028 {
2029 $Content=~s/\A\s+//g;
2030 $Content=~s/\s+\Z//g;
2031 }
2032 if(substr($Content, 0, 1) ne "<") {
2033 $Content = xmlSpecChars_R($Content);
2034 }
2035 return $Content;
2036 }
2037 }
2038 return undef;
2039}
2040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002041sub getInfo($)
2042{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002043 my $DumpPath = $_[0];
2044 return if(not $DumpPath or not -f $DumpPath);
2045
2046 readTUDump($DumpPath);
2047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048 # processing info
2049 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002050
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002051 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002052 setAnonTypedef_All();
2053 }
2054
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002055 getTypeInfo_All();
2056 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002057 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002058 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002059 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002061 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002062 %LibInfo = ();
2063 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002064 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002065 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002066 %TemplateDecl = ();
2067 %StdCxxTypedef = ();
2068 %MissedTypedef = ();
2069 %Typedef_Tr = ();
2070 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002071 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002073 # clean cache
2074 delete($Cache{"getTypeAttr"});
2075 delete($Cache{"getTypeDeclId"});
2076
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002077 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002078 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002079 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002080 }
2081 else
2082 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002083 if($BinaryOnly and not $ExtendedCheck)
2084 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002085 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002086 }
2087 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002088 remove_Unused($Version, "Extended");
2089 }
2090 }
2091
2092 if($CheckInfo)
2093 {
2094 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2095 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2096 }
2097
2098 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2099 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002100 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002101 }
2102
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002103 if($Debug) {
2104 # debugMangling($Version);
2105 }
2106}
2107
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002108sub readTUDump($)
2109{
2110 my $DumpPath = $_[0];
2111
2112 open(TU_DUMP, $DumpPath);
2113 local $/ = undef;
2114 my $Content = <TU_DUMP>;
2115 close(TU_DUMP);
2116
2117 unlink($DumpPath);
2118
2119 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002120 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002121
2122 # clean memory
2123 undef $Content;
2124
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002125 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002126
2127 foreach (0 .. $#Lines)
2128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002129 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002130 { # get a number and attributes of a node
2131 next if(not $NodeType{$2});
2132 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002133 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002134 }
2135
2136 # clean memory
2137 delete($Lines[$_]);
2138 }
2139
2140 # clean memory
2141 undef @Lines;
2142}
2143
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002144sub simplifyConstants()
2145{
2146 foreach my $Constant (keys(%{$Constants{$Version}}))
2147 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002148 if(defined $Constants{$Version}{$Constant}{"Header"})
2149 {
2150 my $Value = $Constants{$Version}{$Constant}{"Value"};
2151 if(defined $EnumConstants{$Version}{$Value}) {
2152 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2153 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002154 }
2155 }
2156}
2157
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002158sub simplifyNames()
2159{
2160 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2161 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002162 if($Typedef_Eq{$Version}{$Base}) {
2163 next;
2164 }
2165 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2166 if($#Translations==0)
2167 {
2168 if(length($Translations[0])<=length($Base)) {
2169 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2170 }
2171 }
2172 else
2173 { # select most appropriate
2174 foreach my $Tr (@Translations)
2175 {
2176 if($Base=~/\A\Q$Tr\E/)
2177 {
2178 $Typedef_Eq{$Version}{$Base} = $Tr;
2179 last;
2180 }
2181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002182 }
2183 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002184 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002185 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002186 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002187 if(not $TypeName) {
2188 next;
2189 }
2190 next if(index($TypeName,"<")==-1);# template instances only
2191 if($TypeName=~/>(::\w+)+\Z/)
2192 { # skip unused types
2193 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002195 foreach my $Base (sort {length($b)<=>length($a)}
2196 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002197 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002198 next if(not $Base);
2199 next if(index($TypeName,$Base)==-1);
2200 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002201 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002202 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002203 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2204 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2205 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002206 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002207 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2208 {
2209 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2210 {
2211 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2212 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002213 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002214 }
2215 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002218 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002219 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002220 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2221 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002222 }
2223}
2224
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002225sub setAnonTypedef_All()
2226{
2227 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2228 {
2229 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2230 {
2231 if(isAnon(getNameByInfo($InfoId))) {
2232 $TypedefToAnon{getTypeId($InfoId)} = 1;
2233 }
2234 }
2235 }
2236}
2237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002238sub setTemplateParams_All()
2239{
2240 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2241 {
2242 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2243 setTemplateParams($_);
2244 }
2245 }
2246}
2247
2248sub setTemplateParams($)
2249{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002250 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002251 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002252 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002253 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002254 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002255 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002256 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002257 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002258 setTemplateInstParams($_[0], $TmplInst_Id);
2259 }
2260 }
2261
2262 $BasicTemplate{$Version}{$Tid} = $_[0];
2263
2264 if(my $Prms = getTreeAttr_Prms($_[0]))
2265 {
2266 if(my $Valu = getTreeAttr_Valu($Prms))
2267 {
2268 my $Vector = getTreeVec($Valu);
2269 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2270 {
2271 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2272 {
2273 if(my $Name = getNameByInfo($Val))
2274 {
2275 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2276 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2277 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2278 }
2279 else {
2280 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2281 }
2282 }
2283 }
2284 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002286 }
2287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002288 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002289 {
2290 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2291 {
2292 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002293 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002294 }
2295 }
2296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002297}
2298
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002299sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002300{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002301 my ($Tmpl, $Inst) = @_;
2302
2303 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002304 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002305 my ($Params_InfoId, $ElemId) = ();
2306 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2307 $Params_InfoId = $1;
2308 }
2309 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2310 $ElemId = $1;
2311 }
2312 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002314 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2315 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2316 {
2317 my ($PPos, $PTypeId) = ($1, $2);
2318 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2319 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002320 if($PType eq "template_type_parm") {
2321 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002322 }
2323 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002324 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2325 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002326 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002327 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002328 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002329 else
2330 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002331 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002332 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002334 }
2335 }
2336 }
2337}
2338
2339sub getTypeDeclId($)
2340{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002341 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002342 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002343 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2344 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2345 }
2346 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2347 {
2348 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2349 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2350 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002353 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002354}
2355
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002356sub getTypeInfo_All()
2357{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002358 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002359 { # support for GCC < 4.5
2360 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2361 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2362 # FIXME: check GCC versions
2363 addMissedTypes_Pre();
2364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002365
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002366 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002367 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2369 if($IType=~/_type\Z/ and $IType ne "function_type"
2370 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002371 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002372 }
2373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002374
2375 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002376 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002377 "Name" => "...",
2378 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002379 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002380 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002381 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002382
2383 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002384 { # support for GCC < 4.5
2385 addMissedTypes_Post();
2386 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002387
2388 if($ADD_TMPL_INSTANCES)
2389 {
2390 # templates
2391 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2392 {
2393 if(defined $TemplateMap{$Version}{$Tid}
2394 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2395 {
2396 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2397 {
2398 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2399 {
2400 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2401 {
2402 if(my %MAttr = getTypeAttr($MembTypeId))
2403 {
2404 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2405 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2406 }
2407 }
2408 }
2409 }
2410 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2411 {
2412 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2413 {
2414 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2415
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002416 if($NBid ne $Bid
2417 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002418 {
2419 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2420 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2421 }
2422 }
2423 }
2424 }
2425 }
2426 }
2427}
2428
2429sub createType($$)
2430{
2431 my ($Attr, $LibVersion) = @_;
2432 my $NewId = ++$MAX_ID;
2433
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002434 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002435 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002436 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002437
2438 return "$NewId";
2439}
2440
2441sub instType($$$)
2442{ # create template instances
2443 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002444
2445 if(not $TypeInfo{$LibVersion}{$Tid}) {
2446 return undef;
2447 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002448 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2449
2450 foreach my $Key (sort keys(%{$Map}))
2451 {
2452 if(my $Val = $Map->{$Key})
2453 {
2454 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2455
2456 if(defined $Attr->{"NameSpace"}) {
2457 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2458 }
2459 foreach (keys(%{$Attr->{"TParam"}})) {
2460 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2461 }
2462 }
2463 else
2464 { # remove absent
2465 # _Traits, etc.
2466 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002467 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002468 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2469 }
2470 foreach (keys(%{$Attr->{"TParam"}}))
2471 {
2472 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2473 delete($Attr->{"TParam"}{$_});
2474 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002475 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002476 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2477 }
2478 }
2479 }
2480 }
2481
2482 my $Tmpl = 0;
2483
2484 if(defined $Attr->{"TParam"})
2485 {
2486 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2487 {
2488 my $PName = $Attr->{"TParam"}{$_}{"name"};
2489
2490 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2491 {
2492 my %Base = get_BaseType($PTid, $LibVersion);
2493
2494 if($Base{"Type"} eq "TemplateParam"
2495 or defined $Base{"Template"})
2496 {
2497 $Tmpl = 1;
2498 last
2499 }
2500 }
2501 }
2502 }
2503
2504 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2505 return "$Id";
2506 }
2507 else
2508 {
2509 if(not $Tmpl) {
2510 delete($Attr->{"Template"});
2511 }
2512
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002513 my $New = createType($Attr, $LibVersion);
2514
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002515 my %EMap = ();
2516 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2517 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2518 }
2519 foreach (keys(%{$Map})) {
2520 $EMap{$_} = $Map->{$_};
2521 }
2522
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002523 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2524 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002525 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002526 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002527 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 {
2530 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2531
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002532 if($NBid ne $Bid
2533 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002534 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002535 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2536 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002537 }
2538 }
2539 }
2540
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002541 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002542 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002543 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2544 {
2545 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2546 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2547 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002548 }
2549 }
2550
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002551 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002552 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002553 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2554 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002555 }
2556 }
2557
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002558 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2559 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002560 }
2561
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002562 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002564}
2565
2566sub addMissedTypes_Pre()
2567{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002568 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002569 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2570 { # detecting missed typedefs
2571 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2572 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002573 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002574 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002575 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002576 if($TypeType eq "Unknown")
2577 { # template_type_parm
2578 next;
2579 }
2580 my $TypeDeclId = getTypeDeclId($TypeId);
2581 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2582 my $TypedefName = getNameByInfo($MissedTDid);
2583 next if(not $TypedefName);
2584 next if($TypedefName eq "__float80");
2585 next if(isAnon($TypedefName));
2586 if(not $TypeDeclId
2587 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002588 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002589 }
2590 }
2591 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002592 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002593 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002594 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002595 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002597 next;
2598 }
2599 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002601 if(not $TypedefName) {
2602 next;
2603 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002604 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605 my %MissedInfo = ( # typedef info
2606 "Name" => $TypedefName,
2607 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002608 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002609 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002610 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 my ($H, $L) = getLocation($MissedTDid);
2612 $MissedInfo{"Header"} = $H;
2613 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002614 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 { # other types
2616 next;
2617 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002618 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002619 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 next;
2621 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002622 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002623 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002624 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002626 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002627 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002628 next;
2629 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002630 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631 next;
2632 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002634 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635 next;
2636 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002637 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002638 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 next;
2640 }
2641 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002642
2643 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2644
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002645 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002647 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002648 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002649 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002650
2651 # add missed & remove other
2652 $TypeInfo{$Version} = \%AddTypes;
2653 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654}
2655
2656sub addMissedTypes_Post()
2657{
2658 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2659 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002660 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2661 {
2662 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2663 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2664 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2665 }
2666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002667 }
2668}
2669
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002670sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002671{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002672 my $TypeId = $_[0];
2673 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2674 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002676 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002678}
2679
2680sub getArraySize($$)
2681{
2682 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002683 if(my $Size = getSize($TypeId))
2684 {
2685 my $Elems = $Size/$BYTE_SIZE;
2686 while($BaseName=~s/\s*\[(\d+)\]//) {
2687 $Elems/=$1;
2688 }
2689 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2690 {
2691 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2692 $Elems/=$BasicSize;
2693 }
2694 }
2695 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002697 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698}
2699
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002700sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002701{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002702 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002703 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002704 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2705 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002706 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002707 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2708 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2709 if(not $NodeType)
2710 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002711 return ();
2712 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002713 if($NodeType eq "tree_vec")
2714 {
2715 if($Pos!=$#Positions)
2716 { # select last vector of parameters ( ns<P1>::type<P2> )
2717 next;
2718 }
2719 }
2720 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2721 foreach my $P (@Params)
2722 {
2723 if($P eq "") {
2724 return ();
2725 }
2726 elsif($P ne "\@skip\@") {
2727 @TmplParams = (@TmplParams, $P);
2728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729 }
2730 }
2731 return @TmplParams;
2732}
2733
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002734sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002735{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002736 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002737 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 if(defined $TypeInfo{$Version}{$TypeId}
2739 and $TypeInfo{$Version}{$TypeId}{"Name"})
2740 { # already created
2741 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2744 { # incomplete type
2745 return ();
2746 }
2747 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2748
2749 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002750 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002751
2752 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2753 {
2754 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2755 {
2756 if($Info=~/qual[ ]*:/)
2757 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002758 my $NewId = ++$MAX_ID;
2759
2760 $MissedBase{$Version}{$TypeId} = "$NewId";
2761 $MissedBase_R{$Version}{$NewId} = $TypeId;
2762 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2763 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002764 }
2765 }
2766 $TypeAttr{"Type"} = "Typedef";
2767 }
2768 else {
2769 $TypeAttr{"Type"} = getTypeType($TypeId);
2770 }
2771
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002772 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2773 {
2774 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2775 { # local code
2776 return ();
2777 }
2778 }
2779
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002780 if($TypeAttr{"Type"} eq "Unknown") {
2781 return ();
2782 }
2783 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002785 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002786 if(my $TName = $TypeAttr{"Name"})
2787 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002788 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002789 $TName_Tid{$Version}{$TName} = $TypeId;
2790 return %TypeAttr;
2791 }
2792 else {
2793 return ();
2794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002795 }
2796 elsif($TypeAttr{"Type"} eq "Array")
2797 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002798 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2799 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002800 return ();
2801 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002802 if(my $Algn = getAlgn($TypeId)) {
2803 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2804 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002805 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002806 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002808 if(not $BTAttr{"Name"}) {
2809 return ();
2810 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002811 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002812 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002813 if(my $Size = getSize($TypeId)) {
2814 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2815 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002816 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002817 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2818 }
2819 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002820 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002822 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 else
2824 {
2825 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002826 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002827 $TypeAttr{"Name"} = $1."[]".$2;
2828 }
2829 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002830 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002832 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002833 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002834 if($BTAttr{"Header"}) {
2835 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002836 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002837 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002838 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2839 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002840 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002841 return ();
2842 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002843 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002844 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002845 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002846 if($TypeAttr{"Name"})
2847 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002848 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002849
2850 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2851 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002852 { # NOTE: register only one int: with built-in decl
2853 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2854 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2855 }
2856 }
2857 return %TypeAttr;
2858 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002859 else {
2860 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002862 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002863 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2864 {
2865 %TypeAttr = getTrivialTypeAttr($TypeId);
2866 if($TypeAttr{"Name"})
2867 {
2868 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2869 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2870 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2871 }
2872 return %TypeAttr;
2873 }
2874 else {
2875 return ();
2876 }
2877 }
2878 elsif($TypeAttr{"Type"} eq "SizeOf")
2879 {
2880 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2881 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2882 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2883 if($TypeAttr{"Name"})
2884 {
2885 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2886 return %TypeAttr;
2887 }
2888 else {
2889 return ();
2890 }
2891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002892 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002893 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002894 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2895 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002896 return ();
2897 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002898 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002899 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002900 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002903 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002904 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 }
2907 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002908 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002909 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002910 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002911 return ();
2912 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002913 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002914 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002915 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002916 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002917 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002918 }
2919 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002920 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 {
2922 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002923 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002924 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002925 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002926 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2927 }
2928 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002929 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002930 }
2931 }
2932 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002933 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002934 }
2935 if($TypeAttr{"Type"} eq "Typedef")
2936 {
2937 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002938
2939 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2940 return ();
2941 }
2942
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002943 if(isAnon($TypeAttr{"Name"}))
2944 { # anon typedef to anon type: ._N
2945 return ();
2946 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002947
2948 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2949 { # artificial typedef of "struct X" to "X"
2950 $TypeAttr{"Artificial"} = 1;
2951 }
2952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002953 if(my $NS = getNameSpace($TypeDeclId))
2954 {
2955 my $TypeName = $TypeAttr{"Name"};
2956 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2957 { # "some_type" is the typedef to "struct some_type" in C++
2958 if($3) {
2959 $TypeAttr{"Name"} = $3."::".$TypeName;
2960 }
2961 }
2962 else
2963 {
2964 $TypeAttr{"NameSpace"} = $NS;
2965 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002966
2967 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2968 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2969 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 if($BTAttr{"NameSpace"}
2971 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002972 { # types like "std::fpos<__mbstate_t>" are
2973 # not covered by typedefs in the TU dump
2974 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2976 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002977 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002978 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002979 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002980 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002982 }
2983 }
2984 }
2985 }
2986 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002987 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002988 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002989 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002990 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2991 { # typedef int*const TYPEDEF; // first
2992 # int foo(TYPEDEF p); // const is optimized out
2993 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2994 if($BTAttr{"Name"}=~/</)
2995 {
2996 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2997 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002999 }
3000 }
3001 }
3002 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3003 }
3004 if(not $TypeAttr{"Size"})
3005 {
3006 if($TypeAttr{"Type"} eq "Pointer") {
3007 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3008 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003009 elsif($BTAttr{"Size"}) {
3010 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003011 }
3012 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003013 if(my $Algn = getAlgn($TypeId)) {
3014 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3015 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003016 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003017 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3018 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003019 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003020 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003021 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003022 { # typedef to "class Class"
3023 # should not be registered in TName_Tid
3024 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3025 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003027 }
3028 return %TypeAttr;
3029 }
3030}
3031
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003032sub getTreeVec($)
3033{
3034 my %Vector = ();
3035 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3036 {
3037 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3038 { # string length is N-1 because of the null terminator
3039 $Vector{$1} = $2;
3040 }
3041 }
3042 return \%Vector;
3043}
3044
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003045sub get_TemplateParam($$)
3046{
3047 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003048 return () if(not $Type_Id);
3049 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3050 return () if(not $NodeType);
3051 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003053 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003054 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003055 my $Num = getNodeIntCst($Type_Id);
3056 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003057 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 }
3059 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003060 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003061 }
3062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003063 elsif($NodeType eq "string_cst") {
3064 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003066 elsif($NodeType eq "tree_vec")
3067 {
3068 my $Vector = getTreeVec($Type_Id);
3069 my @Params = ();
3070 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3071 {
3072 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3073 push(@Params, $P2);
3074 }
3075 }
3076 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003077 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003078 elsif($NodeType eq "parm_decl")
3079 {
3080 (getNameByInfo($Type_Id));
3081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003082 else
3083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003084 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003085 my $PName = $ParamAttr{"Name"};
3086 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003087 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003088 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003089 if($PName=~/\>/)
3090 {
3091 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 $PName = $Cover;
3093 }
3094 }
3095 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003096 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3098 # template<typename _Key, typename _Compare = std::less<_Key>
3099 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3100 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3101 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3102 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003103 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003105 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003106 }
3107}
3108
3109sub cover_stdcxx_typedef($)
3110{
3111 my $TypeName = $_[0];
3112 if(my @Covers = sort {length($a)<=>length($b)}
3113 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3114 { # take the shortest typedef
3115 # FIXME: there may be more than
3116 # one typedefs to the same type
3117 return $Covers[0];
3118 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003119 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003120 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3121 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3122 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003123 if(my $Cover = $Covers[0])
3124 {
3125 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3126 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003128 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003129 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003130}
3131
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003132sub getNodeIntCst($)
3133{
3134 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003135 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136 if($EnumMembName_Id{$Version}{$CstId}) {
3137 return $EnumMembName_Id{$Version}{$CstId};
3138 }
3139 elsif((my $Value = getTreeValue($CstId)) ne "")
3140 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003141 if($Value eq "0")
3142 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003143 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003144 return "false";
3145 }
3146 else {
3147 return "0";
3148 }
3149 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003150 elsif($Value eq "1")
3151 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003152 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003153 return "true";
3154 }
3155 else {
3156 return "1";
3157 }
3158 }
3159 else {
3160 return $Value;
3161 }
3162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003163 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003164}
3165
3166sub getNodeStrCst($)
3167{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003168 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3169 {
3170 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003171 {
3172 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3173 { # string length is N-1 because of the null terminator
3174 return substr($1, 0, $2-1);
3175 }
3176 else
3177 { # identifier_node
3178 return substr($1, 0, $2);
3179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003181 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003182 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003183}
3184
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003185sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003186{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003187 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003188 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3189 if($Type eq "FieldPtr") {
3190 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3191 }
3192 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3193 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003194 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003195 if($Type eq "MethodPtr")
3196 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003197 if(my $Size = getSize($TypeId))
3198 {
3199 $Size/=$BYTE_SIZE;
3200 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003202 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003203 if(my $Algn = getAlgn($TypeId)) {
3204 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003206 # Return
3207 if($Type eq "FieldPtr")
3208 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003209 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003210 if($ReturnAttr{"Name"}) {
3211 $MemPtrName .= $ReturnAttr{"Name"};
3212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003213 $TypeAttr{"Return"} = $PtrId;
3214 }
3215 else
3216 {
3217 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3218 {
3219 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003220 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3221 if(not $ReturnAttr{"Name"})
3222 { # templates
3223 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003224 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003225 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 $TypeAttr{"Return"} = $ReturnTypeId;
3227 }
3228 }
3229 # Class
3230 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3231 {
3232 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003233 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003234 if($Class{"Name"}) {
3235 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3236 }
3237 else {
3238 $MemPtrName .= " (*)";
3239 }
3240 }
3241 else {
3242 $MemPtrName .= " (*)";
3243 }
3244 # Parameters
3245 if($Type eq "FuncPtr"
3246 or $Type eq "MethodPtr")
3247 {
3248 my @ParamTypeName = ();
3249 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3250 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003252 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003253 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3256 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003258 my $PTypeId = $1;
3259 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003260 if(not $ParamAttr{"Name"})
3261 { # templates (template_type_parm), etc.
3262 return ();
3263 }
3264 if($ParamAttr{"Name"} eq "void") {
3265 last;
3266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003267 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003268 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003269 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003270 push(@ParamTypeName, $ParamAttr{"Name"});
3271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003272 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3273 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003274 }
3275 else {
3276 last;
3277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003278 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003279 else {
3280 last;
3281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003282 }
3283 }
3284 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3285 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003286 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003287 return %TypeAttr;
3288}
3289
3290sub getTreeTypeName($)
3291{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292 my $TypeId = $_[0];
3293 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003295 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003296 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003297 if(my $Name = getNameByInfo($TypeId))
3298 { # bit_size_type
3299 return $Name;
3300 }
3301 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003302 return "unsigned int";
3303 }
3304 else {
3305 return "int";
3306 }
3307 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003308 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003309 return getNameByInfo($1);
3310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003311 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003312 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003313}
3314
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003315sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003317 my $Ptd = pointTo($_[0]);
3318 return 0 if(not $Ptd);
3319 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003320 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003321 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3322 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
3324 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003325 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3326 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003327 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003328 if($InfoT1 eq "pointer_type"
3329 and $InfoT2 eq "function_type") {
3330 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003331 }
3332 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003333 return 0;
3334}
3335
3336sub isMethodPtr($)
3337{
3338 my $Ptd = pointTo($_[0]);
3339 return 0 if(not $Ptd);
3340 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3341 {
3342 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3343 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3344 and $Info=~/ ptrmem /) {
3345 return 1;
3346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003347 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003348 return 0;
3349}
3350
3351sub isFieldPtr($)
3352{
3353 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3354 {
3355 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3356 and $Info=~/ ptrmem /) {
3357 return 1;
3358 }
3359 }
3360 return 0;
3361}
3362
3363sub pointTo($)
3364{
3365 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3366 {
3367 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3368 return $1;
3369 }
3370 }
3371 return "";
3372}
3373
3374sub getTypeTypeByTypeId($)
3375{
3376 my $TypeId = $_[0];
3377 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3378 {
3379 my $NType = $NodeType{$TType};
3380 if($NType eq "Intrinsic") {
3381 return $NType;
3382 }
3383 elsif(isFuncPtr($TypeId)) {
3384 return "FuncPtr";
3385 }
3386 elsif(isMethodPtr($TypeId)) {
3387 return "MethodPtr";
3388 }
3389 elsif(isFieldPtr($TypeId)) {
3390 return "FieldPtr";
3391 }
3392 elsif($NType ne "Other") {
3393 return $NType;
3394 }
3395 }
3396 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003397}
3398
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003399my %UnQual = (
3400 "r"=>"restrict",
3401 "v"=>"volatile",
3402 "c"=>"const",
3403 "cv"=>"const volatile"
3404);
3405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003406sub getQual($)
3407{
3408 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003409 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3410 {
3411 my ($Qual, $To) = ();
3412 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3413 $Qual = $UnQual{$1};
3414 }
3415 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3416 $To = $1;
3417 }
3418 if($Qual and $To) {
3419 return ($Qual, $To);
3420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003421 }
3422 return ();
3423}
3424
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003425sub getQualType($)
3426{
3427 if($_[0] eq "const volatile") {
3428 return "ConstVolatile";
3429 }
3430 return ucfirst($_[0]);
3431}
3432
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003433sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003434{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003435 my $TypeId = $_[0];
3436 my $TypeDeclId = getTypeDeclId($TypeId);
3437 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003438 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003439 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3440 return "Typedef";
3441 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003442 }
3443 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3444 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003445 if(($Qual or $To) and $TypeDeclId
3446 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003447 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003448 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003449 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003450 elsif(not $MissedBase_R{$Version}{$TypeId}
3451 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003452 return "Typedef";
3453 }
3454 elsif($Qual)
3455 { # qualified types
3456 return getQualType($Qual);
3457 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003458
3459 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3460 { # typedef struct { ... } name
3461 $TypeTypedef{$Version}{$TypeId} = $1;
3462 }
3463
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003464 my $TypeType = getTypeTypeByTypeId($TypeId);
3465 if($TypeType eq "Struct")
3466 {
3467 if($TypeDeclId
3468 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3469 return "Template";
3470 }
3471 }
3472 return $TypeType;
3473}
3474
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003475sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003476{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003477 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003478 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003479 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3480 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3481 return 0;
3482 }
3483 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3484 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003485 if(my $TDid = getTypeDeclId($_[0]))
3486 {
3487 if(getTypeId($TDid) eq $_[0]
3488 and getNameByInfo($TDid))
3489 {
3490 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3491 return $1;
3492 }
3493 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003494 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003495 }
3496 }
3497 return 0;
3498}
3499
3500sub selectBaseType($)
3501{
3502 my $TypeId = $_[0];
3503 if(defined $MissedTypedef{$Version}{$TypeId})
3504 { # add missed typedefs
3505 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3506 return ($TypeId, "");
3507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003508 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003509 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3510 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003511
3512 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3513 my $MB = $MissedBase{$Version}{$TypeId};
3514
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003515 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003516 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003517 and (getTypeId($1) ne $TypeId)
3518 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003519 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003520 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003521 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003522 elsif($MB)
3523 { # add base
3524 return ($MB, "");
3525 }
3526 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003527 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003528 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003529 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003530 elsif($Qual or $To)
3531 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003532 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003533 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003534 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003536 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003537 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003539 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003540 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003542 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003543 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003544 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003546 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003547 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003548 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003549 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003551 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003552
3553 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003554}
3555
3556sub getSymbolInfo_All()
3557{
3558 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3559 { # reverse order
3560 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003561 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003562 }
3563 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003564
3565 if($ADD_TMPL_INSTANCES)
3566 {
3567 # templates
3568 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3569 {
3570 my %Map = ();
3571
3572 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3573 {
3574 if(defined $TemplateMap{$Version}{$ClassId})
3575 {
3576 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3577 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3578 }
3579 }
3580 }
3581
3582 if(defined $TemplateMap{$Version}{$Sid})
3583 {
3584 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3585 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3586 }
3587 }
3588
3589 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3590 {
3591 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3592 {
3593 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3594 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3595 }
3596 }
3597 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3598 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3599 }
3600 }
3601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003602}
3603
3604sub getVarInfo_All()
3605{
3606 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3607 { # reverse order
3608 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003609 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003610 }
3611 }
3612}
3613
3614sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003615 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003616}
3617
3618sub getVarInfo($)
3619{
3620 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003621 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003622 {
3623 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3624 if($NSInfoType and $NSInfoType eq "function_decl") {
3625 return;
3626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003627 }
3628 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3629 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3630 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3631 delete($SymbolInfo{$Version}{$InfoId});
3632 return;
3633 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003634 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003635 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003636 delete($SymbolInfo{$Version}{$InfoId});
3637 return;
3638 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003639 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3640 delete($SymbolInfo{$Version}{$InfoId});
3641 return;
3642 }
3643 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003644 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3645 {
3646 if($OSgroup eq "windows")
3647 { # cut the offset
3648 $MnglName=~s/\@\d+\Z//g;
3649 }
3650 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003652 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003653 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003654 { # validate mangled name
3655 delete($SymbolInfo{$Version}{$InfoId});
3656 return;
3657 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003658 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003659 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003660 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003661 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003662 }
3663 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3664 { # non-public global data
3665 delete($SymbolInfo{$Version}{$InfoId});
3666 return;
3667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003669 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003670 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003671 if(not defined $TypeInfo{$Version}{$Rid}
3672 or not $TypeInfo{$Version}{$Rid}{"Name"})
3673 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003674 delete($SymbolInfo{$Version}{$InfoId});
3675 return;
3676 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003677 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3678 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003679 if(defined $Val) {
3680 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3681 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 }
3683 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003684 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3685 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003686 if(not defined $TypeInfo{$Version}{$ClassId}
3687 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3688 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003689 delete($SymbolInfo{$Version}{$InfoId});
3690 return;
3691 }
3692 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003693 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3694 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003696 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003697 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003698 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003699 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003700 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003701 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003702 if(not $CheckHeadersOnly)
3703 {
3704 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3705 {
3706 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3707 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3708 {
3709 if(link_symbol($ShortName, $Version, "-Deps"))
3710 { # "const" global data is mangled as _ZL... in the TU dump
3711 # but not mangled when compiling a C shared library
3712 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3713 }
3714 }
3715 }
3716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003717 if($COMMON_LANGUAGE{$Version} eq "C++")
3718 {
3719 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3720 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003721 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003722 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3723 }
3724 }
3725 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3726 { # try to mangle symbol (link with libraries)
3727 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3728 }
3729 if($OStarget eq "windows")
3730 {
3731 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3732 { # link MS C++ symbols from library with GCC symbols from headers
3733 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3734 }
3735 }
3736 }
3737 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3738 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3739 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003740 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3741 {
3742 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3743 { # non-target symbols
3744 delete($SymbolInfo{$Version}{$InfoId});
3745 return;
3746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003748 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3749 {
3750 if(defined $MissedTypedef{$Version}{$Rid})
3751 {
3752 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3753 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3754 }
3755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003756 }
3757 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003758 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003759 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3760 }
3761 if($ShortName=~/\A(_Z|\?)/) {
3762 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3763 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003764
3765 if($ExtraDump) {
3766 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003768}
3769
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003770sub isConstType($$)
3771{
3772 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003773 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003774 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003775 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003776 }
3777 return ($Base{"Type"} eq "Const");
3778}
3779
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003780sub getTrivialName($$)
3781{
3782 my ($TypeInfoId, $TypeId) = @_;
3783 my %TypeAttr = ();
3784 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3785 if(not $TypeAttr{"Name"}) {
3786 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3787 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003788 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003789 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003790 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003791 if(isAnon($TypeAttr{"Name"}))
3792 {
3793 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003794 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003795 { # searching for a first not anon scope
3796 if($NSId eq $NameSpaceId) {
3797 last;
3798 }
3799 else
3800 {
3801 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3802 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003803 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003804 last;
3805 }
3806 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003807 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003808 }
3809 }
3810 else
3811 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003812 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003813 {
3814 if($NameSpaceId ne $TypeId) {
3815 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817 }
3818 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003819 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003820 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3821 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003822 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003823 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003824 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003825 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003826 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003827 if($TypeAttr{"NameSpace"}) {
3828 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003830 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003831 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3832 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003833 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003834 if(my @TParams = getTParams($TypeId, "Type")) {
3835 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3836 }
3837 else {
3838 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003840 }
3841 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3842}
3843
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003844sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003845{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003846 my $TypeId = $_[0];
3847 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003848
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003849 my %TypeAttr = ();
3850
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003851 if($TemplateDecl{$Version}{$TypeId})
3852 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003853 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003854 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003855
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003856 setTypeAccess($TypeId, \%TypeAttr);
3857 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3858 if(isBuiltIn($TypeAttr{"Header"}))
3859 {
3860 delete($TypeAttr{"Header"});
3861 delete($TypeAttr{"Line"});
3862 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003863
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003864 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003865 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3866 if(not $TypeAttr{"Name"}) {
3867 return ();
3868 }
3869 if(not $TypeAttr{"NameSpace"}) {
3870 delete($TypeAttr{"NameSpace"});
3871 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003872
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003873 if($TypeAttr{"Type"} eq "Intrinsic")
3874 {
3875 if(defined $TypeAttr{"Header"})
3876 {
3877 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3878 { # support for SUSE 11.2
3879 # integer_type has srcp dump{1-2}.i
3880 delete($TypeAttr{"Header"});
3881 }
3882 }
3883 }
3884
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003885 my $Tmpl = undef;
3886
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003887 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003888 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003889 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3890
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003891 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003892 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003893 foreach my $Pos (0 .. $#TParams)
3894 {
3895 my $Val = $TParams[$Pos];
3896 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3897
3898 if(not defined $TypeAttr{"Template"})
3899 {
3900 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3901
3902 if($Base{"Type"} eq "TemplateParam"
3903 or defined $Base{"Template"}) {
3904 $TypeAttr{"Template"} = 1;
3905 }
3906 }
3907
3908 if($Tmpl)
3909 {
3910 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3911 {
3912 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3913
3914 if($Val eq $Arg) {
3915 $TypeAttr{"Template"} = 1;
3916 }
3917 }
3918 }
3919 }
3920
3921 if($Tmpl)
3922 {
3923 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3924 {
3925 if($Pos>$#TParams)
3926 {
3927 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3928 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3929 }
3930 }
3931 }
3932 }
3933
3934 if($ADD_TMPL_INSTANCES)
3935 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003936 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003937 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003938 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003939 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003940 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003941 {
3942 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3943 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3944 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003945 }
3946 if(not getTreeAttr_Binf($TypeId))
3947 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003948 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3949 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3950 }
3951 }
3952 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003953 }
3954 }
3955 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003956
3957 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3958
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003959 if(my $Size = getSize($TypeId))
3960 {
3961 $Size = $Size/$BYTE_SIZE;
3962 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003964 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003965 {
3966 if($ExtraDump)
3967 {
3968 if(not defined $TypeAttr{"Memb"}
3969 and not $Tmpl)
3970 { # declaration only
3971 $TypeAttr{"Forward"} = 1;
3972 }
3973 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003974 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003975
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003976 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003977 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003978 {
3979 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003980 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003981 }
3982 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003983 or $TypeAttr{"Type"} eq "Class")
3984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003985 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003986 if($Skip) {
3987 return ();
3988 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003989 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003990 if(my $Algn = getAlgn($TypeId)) {
3991 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003993 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003994
3995 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3996 {
3997 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003998 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003999 {
4000 if(not isAnon($TypeAttr{"Name"})) {
4001 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4002 }
4003 }
4004 }
4005
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004006 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004007 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4008 {
4009 my @Entries = split(/\n/, $VTable);
4010 foreach (1 .. $#Entries)
4011 {
4012 my $Entry = $Entries[$_];
4013 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004014 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004015 }
4016 }
4017 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004018
4019 if($TypeAttr{"Type"} eq "Enum")
4020 {
4021 if(not $TypeAttr{"NameSpace"})
4022 {
4023 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4024 {
4025 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004026 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004027 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004028 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004029 "Header"=>$TypeAttr{"Header"}
4030 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004031 if(isAnon($TypeAttr{"Name"}))
4032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004033 if($ExtraDump
4034 or is_target_header($TypeAttr{"Header"}, $Version))
4035 {
4036 %{$Constants{$Version}{$MName}} = (
4037 "Value" => $MVal,
4038 "Header" => $TypeAttr{"Header"}
4039 );
4040 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004041 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004042 }
4043 }
4044 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004045 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004046 {
4047 if(defined $TypedefToAnon{$TypeId}) {
4048 $TypeAttr{"AnonTypedef"} = 1;
4049 }
4050 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004052 return %TypeAttr;
4053}
4054
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004055sub simplifyVTable($)
4056{
4057 my $Content = $_[0];
4058 if($Content=~s/ \[with (.+)]//)
4059 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4060 if(my @Elems = separate_Params($1, 0, 0))
4061 {
4062 foreach my $Elem (@Elems)
4063 {
4064 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4065 {
4066 my ($Arg, $Val) = ($1, $2);
4067
4068 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4069 $Content=~s/,\s*$Arg\b//g;
4070 }
4071 else {
4072 $Content=~s/\b$Arg\b/$Val/g;
4073 }
4074 }
4075 }
4076 }
4077 }
4078
4079 return $Content;
4080}
4081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004082sub detect_lang($)
4083{
4084 my $TypeId = $_[0];
4085 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004086 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004087 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004088 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4089 }
4090 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004091 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004092 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 while($Fncs)
4094 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004095 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004096 return 1;
4097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004098 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004099 }
4100 }
4101 return 0;
4102}
4103
4104sub setSpec($$)
4105{
4106 my ($TypeId, $TypeAttr) = @_;
4107 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4108 if($Info=~/\s+spec\s+/) {
4109 $TypeAttr->{"Spec"} = 1;
4110 }
4111}
4112
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004113sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004114{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004115 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004117 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004118 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004119 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 my $Pos = 0;
4121 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4122 {
4123 my ($Access, $BInfoId) = ($1, $2);
4124 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004125
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004126 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004127 { # class A<N>:public A<N-1>
4128 next;
4129 }
4130
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004131 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4132 if(not $CType or $CType eq "template_type_parm"
4133 or $CType eq "typename_type")
4134 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004135 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004138 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004139 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4140 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004141 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004142 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4143 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004144 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004145 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004146 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004147 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4148 }
4149 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004150 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004151 }
4152 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004153 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004154}
4155
4156sub getBinfClassId($)
4157{
4158 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004159 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4160 return $1;
4161 }
4162
4163 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004164}
4165
4166sub unmangledFormat($$)
4167{
4168 my ($Name, $LibVersion) = @_;
4169 $Name = uncover_typedefs($Name, $LibVersion);
4170 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4171 $Name=~s/\(\w+\)(\d)/$1/;
4172 return $Name;
4173}
4174
4175sub modelUnmangled($$)
4176{
4177 my ($InfoId, $Compiler) = @_;
4178 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4179 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4180 }
4181 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4182 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4183 $PureSignature = "~".$PureSignature;
4184 }
4185 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4186 {
4187 my (@Params, @ParamTypes) = ();
4188 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4189 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4190 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4191 }
4192 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4193 { # checking parameters
4194 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004195 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004196 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004197 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004198
4199 if($PName eq "this"
4200 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4201 {
4202 next;
4203 }
4204
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004205 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004206 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004207 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004208 }
4209 @ParamTypes = (@ParamTypes, $PTName);
4210 }
4211 if(@ParamTypes) {
4212 $PureSignature .= "(".join(", ", @ParamTypes).")";
4213 }
4214 else
4215 {
4216 if($Compiler eq "MSVC")
4217 {
4218 $PureSignature .= "(void)";
4219 }
4220 else
4221 { # GCC
4222 $PureSignature .= "()";
4223 }
4224 }
4225 $PureSignature = delete_keywords($PureSignature);
4226 }
4227 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4228 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004229 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004230 $PureSignature = $ClassName."::".$PureSignature;
4231 }
4232 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4233 $PureSignature = $NS."::".$PureSignature;
4234 }
4235 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4236 $PureSignature .= " const";
4237 }
4238 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4239 $PureSignature .= " volatile";
4240 }
4241 my $ShowReturn = 0;
4242 if($Compiler eq "MSVC"
4243 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4244 {
4245 $ShowReturn=1;
4246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004247 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4248 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 {
4250 $ShowReturn=1;
4251 }
4252 if($ShowReturn)
4253 { # mangled names for template function specializations include return value
4254 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4255 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004256 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4258 $PureSignature = $ReturnName." ".$PureSignature;
4259 }
4260 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004261 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004262}
4263
4264sub mangle_symbol($$$)
4265{ # mangling for simple methods
4266 # see gcc-4.6.0/gcc/cp/mangle.c
4267 my ($InfoId, $LibVersion, $Compiler) = @_;
4268 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4269 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4270 }
4271 my $Mangled = "";
4272 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004273 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004274 }
4275 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004276 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004277 }
4278 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4279}
4280
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004281sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004282{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004283 my ($InfoId, $LibVersion) = @_;
4284 return "";
4285}
4286
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004287sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004288{ # see gcc-4.6.0/gcc/cp/mangle.c
4289 my ($InfoId, $LibVersion) = @_;
4290 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004291 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004292 my %Repl = ();# SN_ replacements
4293 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4294 {
4295 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4296 if($MangledClass!~/\AN/) {
4297 $MangledClass = "N".$MangledClass;
4298 }
4299 else {
4300 $MangledClass=~s/E\Z//;
4301 }
4302 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4303 $MangledClass=~s/\AN/NV/;
4304 }
4305 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4306 $MangledClass=~s/\AN/NK/;
4307 }
4308 $Mangled .= $MangledClass;
4309 }
4310 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4311 { # mangled by name due to the absence of structured info
4312 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4313 if($MangledNS!~/\AN/) {
4314 $MangledNS = "N".$MangledNS;
4315 }
4316 else {
4317 $MangledNS=~s/E\Z//;
4318 }
4319 $Mangled .= $MangledNS;
4320 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004321 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004322 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004323 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004324 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004325 foreach (@TPos) {
4326 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4327 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328 }
4329 elsif($TmplParams)
4330 { # remangling mode
4331 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004332 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004333 }
4334 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4335 $Mangled .= "C1";
4336 }
4337 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4338 $Mangled .= "D0";
4339 }
4340 elsif($ShortName)
4341 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004342 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4343 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004344 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004345 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004346 { # "const" global data is mangled as _ZL...
4347 $Mangled .= "L";
4348 }
4349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004350 if($ShortName=~/\Aoperator(\W.*)\Z/)
4351 {
4352 my $Op = $1;
4353 $Op=~s/\A[ ]+//g;
4354 if(my $OpMngl = $OperatorMangling{$Op}) {
4355 $Mangled .= $OpMngl;
4356 }
4357 else { # conversion operator
4358 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4359 }
4360 }
4361 else {
4362 $Mangled .= length($ShortName).$ShortName;
4363 }
4364 if(@TParams)
4365 { # templates
4366 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004367 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004368 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4369 }
4370 $Mangled .= "E";
4371 }
4372 if(not $ClassId and @TParams) {
4373 add_substitution($ShortName, \%Repl, 0);
4374 }
4375 }
4376 if($ClassId or $NameSpace) {
4377 $Mangled .= "E";
4378 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004379 if(@TParams)
4380 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004381 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004382 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4383 }
4384 }
4385 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4386 {
4387 my @Params = ();
4388 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4389 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4390 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4391 }
4392 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4393 { # checking parameters
4394 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4395 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4396 }
4397 if(not @Params) {
4398 $Mangled .= "v";
4399 }
4400 }
4401 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4402 $Mangled = write_stdcxx_substitution($Mangled);
4403 if($Mangled eq "_Z") {
4404 return "";
4405 }
4406 return $Mangled;
4407}
4408
4409sub correct_incharge($$$)
4410{
4411 my ($InfoId, $LibVersion, $Mangled) = @_;
4412 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4413 {
4414 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004415 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004416 }
4417 }
4418 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4419 {
4420 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004421 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004422 }
4423 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004424 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004425 }
4426 }
4427 return $Mangled;
4428}
4429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004430sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004431{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004432 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004434 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004435 return $Name;
4436 }
4437 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004438 while(my $CPos = find_center($TParams, "<"))
4439 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004440 $TParams = substr($TParams, $CPos);
4441 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004442 if($TParams=~s/\A<(.+)>\Z/$1/) {
4443 $Name=~s/<\Q$TParams\E>\Z//;
4444 }
4445 else
4446 { # error
4447 $TParams = "";
4448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004449 return ($Name, $TParams);
4450}
4451
4452sub get_sub_ns($)
4453{
4454 my $Name = $_[0];
4455 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004456 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004457 {
4458 push(@NS, substr($Name, 0, $CPos));
4459 $Name = substr($Name, $CPos);
4460 $Name=~s/\A:://;
4461 }
4462 return (join("::", @NS), $Name);
4463}
4464
4465sub mangle_ns($$$)
4466{
4467 my ($Name, $LibVersion, $Repl) = @_;
4468 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4469 {
4470 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4471 $Mangled=~s/\AN(.+)E\Z/$1/;
4472 return $Mangled;
4473
4474 }
4475 else
4476 {
4477 my ($MangledNS, $SubNS) = ("", "");
4478 ($SubNS, $Name) = get_sub_ns($Name);
4479 if($SubNS) {
4480 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4481 }
4482 $MangledNS .= length($Name).$Name;
4483 add_substitution($MangledNS, $Repl, 0);
4484 return $MangledNS;
4485 }
4486}
4487
4488sub mangle_param($$$)
4489{
4490 my ($PTid, $LibVersion, $Repl) = @_;
4491 my ($MPrefix, $Mangled) = ("", "");
4492 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004493 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004494 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004495 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004496 if(not $BaseType_Name) {
4497 return "";
4498 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004499 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004500 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004501 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4502 while($Suffix=~/(&|\*|const)\Z/)
4503 {
4504 if($Suffix=~s/[ ]*&\Z//) {
4505 $MPrefix .= "R";
4506 }
4507 if($Suffix=~s/[ ]*\*\Z//) {
4508 $MPrefix .= "P";
4509 }
4510 if($Suffix=~s/[ ]*const\Z//)
4511 {
4512 if($MPrefix=~/R|P/
4513 or $Suffix=~/&|\*/) {
4514 $MPrefix .= "K";
4515 }
4516 }
4517 if($Suffix=~s/[ ]*volatile\Z//) {
4518 $MPrefix .= "V";
4519 }
4520 #if($Suffix=~s/[ ]*restrict\Z//) {
4521 #$MPrefix .= "r";
4522 #}
4523 }
4524 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4525 $Mangled .= $Token;
4526 }
4527 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4528 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004529 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004530 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004531 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004532 foreach (@TPos) {
4533 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4534 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004535 }
4536 elsif($TmplParams)
4537 { # remangling mode
4538 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004539 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004540 }
4541 my $MangledNS = "";
4542 my ($SubNS, $SName) = get_sub_ns($ShortName);
4543 if($SubNS) {
4544 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4545 }
4546 $MangledNS .= length($SName).$SName;
4547 if(@TParams) {
4548 add_substitution($MangledNS, $Repl, 0);
4549 }
4550 $Mangled .= "N".$MangledNS;
4551 if(@TParams)
4552 { # templates
4553 $Mangled .= "I";
4554 foreach my $TParam (@TParams) {
4555 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4556 }
4557 $Mangled .= "E";
4558 }
4559 $Mangled .= "E";
4560 }
4561 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4562 {
4563 if($BaseType{"Type"} eq "MethodPtr") {
4564 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4565 }
4566 else {
4567 $Mangled .= "PF";
4568 }
4569 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4570 my @Params = keys(%{$BaseType{"Param"}});
4571 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4572 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4573 }
4574 if(not @Params) {
4575 $Mangled .= "v";
4576 }
4577 $Mangled .= "E";
4578 }
4579 elsif($BaseType{"Type"} eq "FieldPtr")
4580 {
4581 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4582 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4583 }
4584 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4585 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4586 {
4587 if($Mangled eq $Optimized)
4588 {
4589 if($ShortName!~/::/)
4590 { # remove "N ... E"
4591 if($MPrefix) {
4592 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4593 }
4594 else {
4595 $Mangled=~s/\AN(.+)E\Z/$1/g;
4596 }
4597 }
4598 }
4599 else {
4600 $Mangled = $Optimized;
4601 }
4602 }
4603 add_substitution($Mangled, $Repl, 1);
4604 return $Mangled;
4605}
4606
4607sub mangle_template_param($$$)
4608{ # types + literals
4609 my ($TParam, $LibVersion, $Repl) = @_;
4610 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4611 return mangle_param($TPTid, $LibVersion, $Repl);
4612 }
4613 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4614 { # class_name<1u>::method(...)
4615 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4616 }
4617 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4618 { # class_name<(signed char)1>::method(...)
4619 return "L".$IntrinsicMangling{$1}.$2."E";
4620 }
4621 elsif($TParam eq "true")
4622 { # class_name<true>::method(...)
4623 return "Lb1E";
4624 }
4625 elsif($TParam eq "false")
4626 { # class_name<true>::method(...)
4627 return "Lb0E";
4628 }
4629 else { # internal error
4630 return length($TParam).$TParam;
4631 }
4632}
4633
4634sub add_substitution($$$)
4635{
4636 my ($Value, $Repl, $Rec) = @_;
4637 if($Rec)
4638 { # subtypes
4639 my @Subs = ($Value);
4640 while($Value=~s/\A(R|P|K)//) {
4641 push(@Subs, $Value);
4642 }
4643 foreach (reverse(@Subs)) {
4644 add_substitution($_, $Repl, 0);
4645 }
4646 return;
4647 }
4648 return if($Value=~/\AS(\d*)_\Z/);
4649 $Value=~s/\AN(.+)E\Z/$1/g;
4650 return if(defined $Repl->{$Value});
4651 return if(length($Value)<=1);
4652 return if($StdcxxMangling{$Value});
4653 # check for duplicates
4654 my $Base = $Value;
4655 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4656 {
4657 my $Num = $Repl->{$Type};
4658 my $Replace = macro_mangle($Num);
4659 $Base=~s/\Q$Replace\E/$Type/;
4660 }
4661 if(my $OldNum = $Repl->{$Base})
4662 {
4663 $Repl->{$Value} = $OldNum;
4664 return;
4665 }
4666 my @Repls = sort {$b<=>$a} values(%{$Repl});
4667 if(@Repls) {
4668 $Repl->{$Value} = $Repls[0]+1;
4669 }
4670 else {
4671 $Repl->{$Value} = -1;
4672 }
4673 # register duplicates
4674 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004675 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004676 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4677 {
4678 next if($Base eq $Type);
4679 my $Num = $Repl->{$Type};
4680 my $Replace = macro_mangle($Num);
4681 $Base=~s/\Q$Type\E/$Replace/;
4682 $Repl->{$Base} = $Repl->{$Value};
4683 }
4684}
4685
4686sub macro_mangle($)
4687{
4688 my $Num = $_[0];
4689 if($Num==-1) {
4690 return "S_";
4691 }
4692 else
4693 {
4694 my $Code = "";
4695 if($Num<10)
4696 { # S0_, S1_, S2_, ...
4697 $Code = $Num;
4698 }
4699 elsif($Num>=10 and $Num<=35)
4700 { # SA_, SB_, SC_, ...
4701 $Code = chr(55+$Num);
4702 }
4703 else
4704 { # S10_, S11_, S12_
4705 $Code = $Num-26; # 26 is length of english alphabet
4706 }
4707 return "S".$Code."_";
4708 }
4709}
4710
4711sub write_stdcxx_substitution($)
4712{
4713 my $Mangled = $_[0];
4714 if($StdcxxMangling{$Mangled}) {
4715 return $StdcxxMangling{$Mangled};
4716 }
4717 else
4718 {
4719 my @Repls = keys(%StdcxxMangling);
4720 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4721 foreach my $MangledType (@Repls)
4722 {
4723 my $Replace = $StdcxxMangling{$MangledType};
4724 #if($Mangled!~/$Replace/) {
4725 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4726 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4727 #}
4728 }
4729 }
4730 return $Mangled;
4731}
4732
4733sub write_substitution($$)
4734{
4735 my ($Mangled, $Repl) = @_;
4736 if(defined $Repl->{$Mangled}
4737 and my $MnglNum = $Repl->{$Mangled}) {
4738 $Mangled = macro_mangle($MnglNum);
4739 }
4740 else
4741 {
4742 my @Repls = keys(%{$Repl});
4743 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4744 # FIXME: how to apply replacements? by num or by pos
4745 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4746 foreach my $MangledType (@Repls)
4747 {
4748 my $Replace = macro_mangle($Repl->{$MangledType});
4749 if($Mangled!~/$Replace/) {
4750 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4751 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4752 }
4753 }
4754 }
4755 return $Mangled;
4756}
4757
4758sub delete_keywords($)
4759{
4760 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004761 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004762 return $TypeName;
4763}
4764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004765sub uncover_typedefs($$)
4766{
4767 my ($TypeName, $LibVersion) = @_;
4768 return "" if(not $TypeName);
4769 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4770 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4771 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004772 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004773 while($TypeName_New ne $TypeName_Pre)
4774 {
4775 $TypeName_Pre = $TypeName_New;
4776 my $TypeName_Copy = $TypeName_New;
4777 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004778 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004780 if(not $Intrinsic_Keywords{$1}) {
4781 $Words{$1} = 1;
4782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004783 }
4784 foreach my $Word (keys(%Words))
4785 {
4786 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4787 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004788 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004789 if($BaseType_Name=~/\([\*]+\)/)
4790 { # FuncPtr
4791 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4792 {
4793 my $Type_Suffix = $1;
4794 $TypeName_New = $BaseType_Name;
4795 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004796 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004797 }
4798 }
4799 }
4800 else
4801 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004802 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004803 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004804 }
4805 }
4806 }
4807 }
4808 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4809}
4810
4811sub isInternal($)
4812{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004813 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4814 {
4815 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4816 {
4817 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4818 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4819 return 1;
4820 }
4821 }
4822 }
4823 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004824}
4825
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004826sub getDataVal($$)
4827{
4828 my ($InfoId, $TypeId) = @_;
4829 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4830 {
4831 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4832 {
4833 if(defined $LibInfo{$Version}{"info_type"}{$1}
4834 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004835 {
4836 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004837 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004838 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4839 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004840 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004841 if(my $Addr = getTreeAttr_Op($1)) {
4842 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004843 }
4844 }
4845 }
4846 }
4847 else {
4848 return getInitVal($1, $TypeId);
4849 }
4850 }
4851 }
4852 return undef;
4853}
4854
4855sub getInitVal($$)
4856{
4857 my ($InfoId, $TypeId) = @_;
4858 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4859 {
4860 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4861 {
4862 if($InfoType eq "integer_cst")
4863 {
4864 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004865 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004866 { # characters
4867 $Val = chr($Val);
4868 }
4869 return $Val;
4870 }
4871 elsif($InfoType eq "string_cst") {
4872 return getNodeStrCst($InfoId);
4873 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004874 elsif($InfoType eq "var_decl")
4875 {
4876 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4877 return $Name;
4878 }
4879 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004880 }
4881 }
4882 return undef;
4883}
4884
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004885sub set_Class_And_Namespace($)
4886{
4887 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004888 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004889 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004890 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004891 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004892 my $NSInfoId = $1;
4893 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4894 {
4895 if($InfoType eq "namespace_decl") {
4896 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4897 }
4898 elsif($InfoType eq "record_type") {
4899 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4900 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004902 }
4903 }
4904 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4905 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004906 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004907 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004908 { # skip
4909 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004911 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004912
4913 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004914}
4915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916sub debugMangling($)
4917{
4918 my $LibVersion = $_[0];
4919 my %Mangled = ();
4920 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4921 {
4922 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4923 {
4924 if($Mngl=~/\A(_Z|\?)/) {
4925 $Mangled{$Mngl}=$InfoId;
4926 }
4927 }
4928 }
4929 translateSymbols(keys(%Mangled), $LibVersion);
4930 foreach my $Mngl (keys(%Mangled))
4931 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004932 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4933 my $U2 = $tr_name{$Mngl};
4934 if($U1 ne $U2) {
4935 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004936 }
4937 }
4938}
4939
4940sub linkSymbol($)
4941{ # link symbols from shared libraries
4942 # with the symbols from header files
4943 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004944 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004945 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004946 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4947 or $EMERGENCY_MODE_48)
4948 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4949 # 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 +03004950 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004951 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004952 {
4953 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4954 return correct_incharge($InfoId, $Version, $Mangled);
4955 }
4956 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004957 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004958 or not $BinaryOnly
4959 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004960 { # 1. --headers-only mode
4961 # 2. not mangled src-only symbols
4962 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4963 return $Mangled;
4964 }
4965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004966 }
4967 return "";
4968}
4969
4970sub setLanguage($$)
4971{
4972 my ($LibVersion, $Lang) = @_;
4973 if(not $UserLang) {
4974 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4975 }
4976}
4977
4978sub getSymbolInfo($)
4979{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004980 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004981 if(isInternal($InfoId)) {
4982 return;
4983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004984 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4985 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004986 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4987 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004988 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004989 return;
4990 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004991 setFuncAccess($InfoId);
4992 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004993 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4994 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004995 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004996 return;
4997 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004998
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004999 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005000 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005001 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005002 if(not defined $TypeInfo{$Version}{$Return}
5003 or not $TypeInfo{$Version}{$Return}{"Name"})
5004 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005005 delete($SymbolInfo{$Version}{$InfoId});
5006 return;
5007 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005008 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005009 }
5010 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5011 {
5012 if(defined $MissedTypedef{$Version}{$Rid})
5013 {
5014 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5015 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5016 }
5017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005018 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005019 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5020 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005021 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005022 my $Orig = getFuncOrig($InfoId);
5023 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005024 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5025 {
5026 delete($SymbolInfo{$Version}{$InfoId});
5027 return;
5028 }
5029
5030 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005031 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005032 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005033 return;
5034 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005035
5036 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005037 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005038 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5039
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005040 my @TParams = getTParams($Orig, "Func");
5041 if(not @TParams)
5042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005043 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005044 return;
5045 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005046 foreach my $Pos (0 .. $#TParams)
5047 {
5048 my $Val = $TParams[$Pos];
5049 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5050
5051 if($Tmpl)
5052 {
5053 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5054 {
5055 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5056 }
5057 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005058 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005059
5060 if($Tmpl)
5061 {
5062 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5063 {
5064 if($Pos>$#TParams)
5065 {
5066 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5067 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5068 }
5069 }
5070 }
5071
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005072 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5073 { # operator<< <T>, operator>> <T>
5074 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5075 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005076 if(@TParams) {
5077 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5078 }
5079 else {
5080 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5081 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005082 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005083 }
5084 else
5085 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005086 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005087 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005088 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5089 {
5090 if($OSgroup eq "windows")
5091 { # cut the offset
5092 $MnglName=~s/\@\d+\Z//g;
5093 }
5094 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5095
5096 # NOTE: mangling of some symbols may change depending on GCC version
5097 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5098 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5099 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005100
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005101 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005102 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005103 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005104 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005105 return;
5106 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005107 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005108 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005109 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005110 if($Skip)
5111 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005112 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005113 return;
5114 }
5115 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005116 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5117 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5118 }
5119
5120 if(set_Class_And_Namespace($InfoId))
5121 {
5122 delete($SymbolInfo{$Version}{$InfoId});
5123 return;
5124 }
5125
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005126 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5127 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005128 if(not defined $TypeInfo{$Version}{$ClassId}
5129 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5130 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005131 delete($SymbolInfo{$Version}{$InfoId});
5132 return;
5133 }
5134 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005135 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5136 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005137 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005138 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005140 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005141 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005142 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005143 }
5144 if($COMMON_LANGUAGE{$Version} eq "C++")
5145 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005146 # C++ or --headers-only mode
5147 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005148 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005149 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5150 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005151 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005152 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005153 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005154 if(my $Mangled = linkSymbol($InfoId)) {
5155 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005156 }
5157 }
5158 if($OStarget eq "windows")
5159 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005160 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005161 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005162 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005163 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005164 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005165 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005166 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005167 }
5168 }
5169 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005170 else
5171 { # not mangled in C
5172 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5173 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005174 if(not $CheckHeadersOnly
5175 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5176 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5177 {
5178 my $Incorrect = 0;
5179
5180 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5181 {
5182 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5183 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5184 { # mangled in the TU dump, but not mangled in the library
5185 $Incorrect = 1;
5186 }
5187 }
5188 else
5189 {
5190 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5191 { # all C++ functions are not mangled in the TU dump
5192 $Incorrect = 1;
5193 }
5194 }
5195 if($Incorrect)
5196 {
5197 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5198 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5199 }
5200 }
5201 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005202 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005203 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005204 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005205 return;
5206 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005207 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005208 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005209 { # identify virtual and pure virtual functions
5210 # NOTE: constructors cannot be virtual
5211 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5212 # in the TU dump, so taking it from the original symbol
5213 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5214 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5215 { # NOTE: D2 destructors are not present in a v-table
5216 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005218 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005219 if(isInline($InfoId)) {
5220 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005221 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005222 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005223 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005225 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5226 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005227 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005228 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005229 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005230 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005231 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005232 }
5233 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005234 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5235 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005236 if(not $ExtraDump)
5237 {
5238 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5239 { # non-target symbols
5240 delete($SymbolInfo{$Version}{$InfoId});
5241 return;
5242 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5246 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5247 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5248 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005250 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5251 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005252 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 return;
5254 }
5255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005257 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005258 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 return;
5262 }
5263 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005264 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 }
5266 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005267 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5268 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5269 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005271 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5272 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005274 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005275 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005276 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005277 }
5278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005279 if(getFuncLink($InfoId) eq "Static") {
5280 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005282 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5283 {
5284 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5285 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005286 if($Unmangled=~/\.\_\d/)
5287 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005288 delete($SymbolInfo{$Version}{$InfoId});
5289 return;
5290 }
5291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005292 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005293
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005294 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5295 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005297 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5298 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005299 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005300
5301 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5302 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5303 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005304
5305 if($ExtraDump) {
5306 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5307 }
5308}
5309
5310sub guessHeader($)
5311{
5312 my $InfoId = $_[0];
5313 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5314 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5315 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5316 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5317 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5318 {
5319 if(get_filename($HPath) eq $Header)
5320 {
5321 my $HDir = get_filename(get_dirname($HPath));
5322 if($HDir ne "include"
5323 and $HDir=~/\A[a-z]+\Z/i) {
5324 return join_P($HDir, $Header);
5325 }
5326 }
5327 }
5328 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005329}
5330
5331sub isInline($)
5332{ # "body: undefined" in the tree
5333 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005334 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5335 {
5336 if($Info=~/ undefined /i) {
5337 return 0;
5338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005339 }
5340 return 1;
5341}
5342
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005343sub hasThrow($)
5344{
5345 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5346 {
5347 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5348 return getTreeAttr_Unql($1, "unql");
5349 }
5350 }
5351 return 1;
5352}
5353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005354sub getTypeId($)
5355{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005356 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5357 {
5358 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5359 return $1;
5360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005361 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005362 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005363}
5364
5365sub setTypeMemb($$)
5366{
5367 my ($TypeId, $TypeAttr) = @_;
5368 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005369 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005370 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005371 if($TypeType eq "Enum")
5372 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005373 my $MInfoId = getTreeAttr_Csts($TypeId);
5374 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005375 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005376 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5377 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005378 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005379 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5380 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005381 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005382 }
5383 }
5384 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5385 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005386 my $MInfoId = getTreeAttr_Flds($TypeId);
5387 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005388 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005389 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5390 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005391 if(not $IType or $IType ne "field_decl")
5392 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005393
5394 if($IType eq "var_decl")
5395 { # static field
5396 $StaticFields = 1;
5397 }
5398
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005399 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005400 next;
5401 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005402 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005403 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005404 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005405 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005406 }
5407 if(not $StructMembName)
5408 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005409 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005411 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5413 if(isAnon($UnnamedTName))
5414 { # rename unnamed fields to unnamed0, unnamed1, ...
5415 $StructMembName = "unnamed".($UnnamedPos++);
5416 }
5417 }
5418 }
5419 if(not $StructMembName)
5420 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005421 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005422 next;
5423 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005424 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005425 if(defined $MissedTypedef{$Version}{$MembTypeId})
5426 {
5427 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5428 $MembTypeId = $AddedTid;
5429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005430 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005431
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005432 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5433 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005434 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005435 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005436 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5437 }
5438 if($MInfo=~/spec:\s*mutable /)
5439 { # mutable fields
5440 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005442 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005443 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5444 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005445 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005446 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005447 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005448 }
5449 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005450 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005451 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5452 { # template
5453 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5454 }
5455 else {
5456 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005458 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005459
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005460 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005461 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462 }
5463 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005464
5465 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005466}
5467
5468sub setFuncParams($)
5469{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005470 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005471 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005472
5473 my $FType = getFuncType($InfoId);
5474
5475 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005476 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005477 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5478 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005479 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005480 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005481 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5482 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005483 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005484 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005486 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005487 else
5488 { # skip
5489 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005491 # skip "this"-parameter
5492 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005493 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005494 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005496 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005497 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5498 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5499 if(not $ParamName)
5500 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005501 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005503 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5504 {
5505 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5506 $ParamTypeId = $AddedTid;
5507 }
5508 }
5509 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005510 if(not $PType or $PType eq "Unknown") {
5511 return 1;
5512 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005513 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005514 if(not $PTName) {
5515 return 1;
5516 }
5517 if($PTName eq "void") {
5518 last;
5519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005520 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005521 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005522 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005523 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005524 $ParamInfoId = getNextElem($ParamInfoId);
5525 next;
5526 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005527 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005528
5529 if(my %Base = get_BaseType($ParamTypeId, $Version))
5530 {
5531 if(defined $Base{"Template"}) {
5532 return 1;
5533 }
5534 }
5535
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005536 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005537 if(my $Algn = getAlgn($ParamInfoId)) {
5538 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005540 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5541 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005542 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
5544 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005545 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005546 if($ParamName ne "this" or $FType ne "Method") {
5547 $PPos += 1;
5548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005549 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005550 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005551 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005552 }
5553 return 0;
5554}
5555
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005556sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005558 my ($InfoId, $Vtt_Pos) = @_;
5559 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005560 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005561 my $FType = getFuncType($InfoId);
5562
5563 if($FType eq "Method")
5564 {
5565 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005566 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005567 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005568 if(not $ParamListElemId)
5569 { # foo(...)
5570 return 1;
5571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005573 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005574 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005575 { # actual params: may differ from formal args
5576 # formal int*const
5577 # actual: int*
5578 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005579 {
5580 $Vtt_Pos=-1;
5581 $ParamListElemId = getNextElem($ParamListElemId);
5582 next;
5583 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005584 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5585 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005586 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005587 $HaveVoid = 1;
5588 last;
5589 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005590 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005591 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005592 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5593 {
5594 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5595 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5596 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005597 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005598 }
5599 }
5600 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5601 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005602 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005603 { # params
5604 if($OldId ne $ParamTypeId)
5605 {
5606 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5607 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5608
5609 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5610 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5611 }
5612 }
5613 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005614 }
5615 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005616 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005617 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005618 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5619 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005620 if($PurpType eq "nop_expr")
5621 { # func ( const char* arg = (const char*)(void*)0 )
5622 $PurpId = getTreeAttr_Op($PurpId);
5623 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005624 my $Val = getInitVal($PurpId, $ParamTypeId);
5625 if(defined $Val) {
5626 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 }
5629 }
5630 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005631 if($Pos!=0 or $FType ne "Method") {
5632 $PPos += 1;
5633 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005634 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005635 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005636 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005637}
5638
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005639sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005640{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005641 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5642 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005643 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5644 return $1;
5645 }
5646 }
5647 return "";
5648}
5649
5650sub getTreeAttr_Chain($)
5651{
5652 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5653 {
5654 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5655 return $1;
5656 }
5657 }
5658 return "";
5659}
5660
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005661sub getTreeAttr_Unql($)
5662{
5663 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5664 {
5665 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5666 return $1;
5667 }
5668 }
5669 return "";
5670}
5671
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005672sub getTreeAttr_Scpe($)
5673{
5674 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5675 {
5676 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5677 return $1;
5678 }
5679 }
5680 return "";
5681}
5682
5683sub getTreeAttr_Type($)
5684{
5685 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5686 {
5687 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5688 return $1;
5689 }
5690 }
5691 return "";
5692}
5693
5694sub getTreeAttr_Name($)
5695{
5696 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5697 {
5698 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5699 return $1;
5700 }
5701 }
5702 return "";
5703}
5704
5705sub getTreeAttr_Mngl($)
5706{
5707 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5708 {
5709 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5710 return $1;
5711 }
5712 }
5713 return "";
5714}
5715
5716sub getTreeAttr_Prms($)
5717{
5718 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5719 {
5720 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5721 return $1;
5722 }
5723 }
5724 return "";
5725}
5726
5727sub getTreeAttr_Fncs($)
5728{
5729 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5730 {
5731 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5732 return $1;
5733 }
5734 }
5735 return "";
5736}
5737
5738sub getTreeAttr_Csts($)
5739{
5740 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5741 {
5742 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5743 return $1;
5744 }
5745 }
5746 return "";
5747}
5748
5749sub getTreeAttr_Purp($)
5750{
5751 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5752 {
5753 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5754 return $1;
5755 }
5756 }
5757 return "";
5758}
5759
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005760sub getTreeAttr_Op($)
5761{
5762 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5763 {
5764 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5765 return $1;
5766 }
5767 }
5768 return "";
5769}
5770
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005771sub getTreeAttr_Valu($)
5772{
5773 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5774 {
5775 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5776 return $1;
5777 }
5778 }
5779 return "";
5780}
5781
5782sub getTreeAttr_Flds($)
5783{
5784 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5785 {
5786 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5787 return $1;
5788 }
5789 }
5790 return "";
5791}
5792
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005793sub getTreeAttr_Binf($)
5794{
5795 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5796 {
5797 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5798 return $1;
5799 }
5800 }
5801 return "";
5802}
5803
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005804sub getTreeAttr_Args($)
5805{
5806 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5807 {
5808 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005809 return $1;
5810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005811 }
5812 return "";
5813}
5814
5815sub getTreeValue($)
5816{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005817 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5818 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005819 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5820 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005822 }
5823 return "";
5824}
5825
5826sub getTreeAccess($)
5827{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005828 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005829 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005830 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5831 {
5832 my $Access = $1;
5833 if($Access eq "prot") {
5834 return "protected";
5835 }
5836 elsif($Access eq "priv") {
5837 return "private";
5838 }
5839 }
5840 elsif($Info=~/ protected /)
5841 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005842 return "protected";
5843 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005844 elsif($Info=~/ private /)
5845 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005846 return "private";
5847 }
5848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005849 return "public";
5850}
5851
5852sub setFuncAccess($)
5853{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005854 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005855 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005856 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005857 }
5858 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005859 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005860 }
5861}
5862
5863sub setTypeAccess($$)
5864{
5865 my ($TypeId, $TypeAttr) = @_;
5866 my $Access = getTreeAccess($TypeId);
5867 if($Access eq "protected") {
5868 $TypeAttr->{"Protected"} = 1;
5869 }
5870 elsif($Access eq "private") {
5871 $TypeAttr->{"Private"} = 1;
5872 }
5873}
5874
5875sub setFuncKind($)
5876{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005877 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5878 {
5879 if($Info=~/pseudo tmpl/) {
5880 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5881 }
5882 elsif($Info=~/ constructor /) {
5883 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5884 }
5885 elsif($Info=~/ destructor /) {
5886 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005888 }
5889}
5890
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005891sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005892{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005893 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5894 {
5895 if($Info=~/spec[ ]*:[ ]*pure /) {
5896 return "PureVirt";
5897 }
5898 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5899 return "Virt";
5900 }
5901 elsif($Info=~/ pure\s+virtual /)
5902 { # support for old GCC versions
5903 return "PureVirt";
5904 }
5905 elsif($Info=~/ virtual /)
5906 { # support for old GCC versions
5907 return "Virt";
5908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005909 }
5910 return "";
5911}
5912
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913sub getFuncLink($)
5914{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005915 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5916 {
5917 if($Info=~/link[ ]*:[ ]*static /) {
5918 return "Static";
5919 }
5920 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005921 return $1;
5922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005923 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005924 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005925}
5926
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005927sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005929 my ($Symbol, $LibVersion) = @_;
5930 return "" if(not $Symbol or not $LibVersion);
5931 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5932 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005934 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5935 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5936 }
5937 }
5938 if($NS)
5939 {
5940 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5941 return $NS;
5942 }
5943 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005944 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945 while($NS=~s/::[^:]+\Z//)
5946 {
5947 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5948 return $NS;
5949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950 }
5951 }
5952 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005953
5954 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005955}
5956
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005957sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005958{
5959 my ($TypeName, $LibVersion) = @_;
5960 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005961 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005963 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5964 return $NS;
5965 }
5966 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005967 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968 while($NS=~s/::[^:]+\Z//)
5969 {
5970 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5971 return $NS;
5972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 }
5974 }
5975 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005976 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005977}
5978
5979sub getNameSpace($)
5980{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005981 my $InfoId = $_[0];
5982 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005984 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005986 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005987 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005988 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5989 {
5990 my $NameSpace = getTreeStr($1);
5991 if($NameSpace eq "::")
5992 { # global namespace
5993 return "";
5994 }
5995 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5996 $NameSpace = $BaseNameSpace."::".$NameSpace;
5997 }
5998 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5999 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006000 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006001 else {
6002 return "";
6003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006004 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006005 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006006 { # inside data type
6007 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6008 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006011 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006012 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006013}
6014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015sub getEnumMembVal($)
6016{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006017 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006019 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6020 {
6021 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6022 {
6023 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6024 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6025 return getTreeValue($1);
6026 }
6027 else
6028 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6029 return getTreeValue($1);
6030 }
6031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006032 }
6033 }
6034 return "";
6035}
6036
6037sub getSize($)
6038{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006039 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6040 {
6041 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6042 return getTreeValue($1);
6043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006044 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006045 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046}
6047
6048sub getAlgn($)
6049{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6051 {
6052 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6053 return $1;
6054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057}
6058
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006059sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006060{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006061 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6062 {
6063 if($Info=~/ bitfield /) {
6064 return getSize($_[0]);
6065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006067 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068}
6069
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006070sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006072 if(my $Chan = getTreeAttr_Chan($_[0])) {
6073 return $Chan;
6074 }
6075 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6076 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006078 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006079}
6080
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006081sub registerHeader($$)
6082{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006083 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006084 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 return "";
6086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006087 if(is_abs($Header) and not -f $Header)
6088 { # incorrect absolute path
6089 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006090 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006091 if(skipHeader($Header, $LibVersion))
6092 { # skip
6093 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006095 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6096 {
6097 detect_header_includes($Header_Path, $LibVersion);
6098
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006099 if(defined $Tolerance and $Tolerance=~/3/)
6100 { # 3 - skip headers that include non-Linux headers
6101 if($OSgroup ne "windows")
6102 {
6103 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6104 {
6105 if(specificHeader($Inc, "windows")) {
6106 return "";
6107 }
6108 }
6109 }
6110 }
6111
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006112 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6113 { # redirect
6114 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6115 or skipHeader($RHeader_Path, $LibVersion))
6116 { # skip
6117 return "";
6118 }
6119 $Header_Path = $RHeader_Path;
6120 }
6121 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6122 { # skip
6123 return "";
6124 }
6125
6126 if(my $HName = get_filename($Header_Path))
6127 { # register
6128 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6129 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6130 }
6131
6132 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6133 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006134 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006135 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006136 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006137 }
6138
6139 if($CheckHeadersOnly
6140 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6141 { # /usr/include/c++/4.6.1/...
6142 $STDCXX_TESTING = 1;
6143 }
6144
6145 return $Header_Path;
6146 }
6147 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006148}
6149
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006150sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006151{
6152 my ($Dir, $WithDeps, $LibVersion) = @_;
6153 $Dir=~s/[\/\\]+\Z//g;
6154 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006155 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006156
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006157 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006158 if($WithDeps)
6159 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006160 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6161 return;
6162 }
6163 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6164 $Mode = "DepsOnly";
6165 }
6166 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006167 else
6168 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006169 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6170 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6171 return;
6172 }
6173 }
6174 $Header_Dependency{$LibVersion}{$Dir} = 1;
6175 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6176 if($Mode eq "DepsOnly")
6177 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006178 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179 $Header_Dependency{$LibVersion}{$Path} = 1;
6180 }
6181 return;
6182 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006183 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006184 {
6185 if($WithDeps)
6186 {
6187 my $SubDir = $Path;
6188 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6189 { # register all sub directories
6190 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6191 }
6192 }
6193 next if(is_not_header($Path));
6194 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006195 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006196 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6198 }
6199 }
6200 if(get_filename($Dir) eq "include")
6201 { # search for "lib/include/" directory
6202 my $LibDir = $Dir;
6203 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006204 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006205 }
6206 }
6207}
6208
6209sub parse_redirect($$$)
6210{
6211 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006212 my @Errors = ();
6213 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6214 push(@Errors, $1);
6215 }
6216 my $Redirect = "";
6217 foreach (@Errors)
6218 {
6219 s/\s{2,}/ /g;
6220 if(/(only|must\ include
6221 |update\ to\ include
6222 |replaced\ with
6223 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006224 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 {
6226 $Redirect = $2;
6227 last;
6228 }
6229 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6230 {
6231 $Redirect = $2;
6232 last;
6233 }
6234 elsif(/this\ header\ should\ not\ be\ used
6235 |programs\ should\ not\ directly\ include
6236 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6237 |is\ not\ supported\ API\ for\ general\ use
6238 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006239 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006240 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6241 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6242 }
6243 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006244 if($Redirect)
6245 {
6246 $Redirect=~s/\A<//g;
6247 $Redirect=~s/>\Z//g;
6248 }
6249 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006250}
6251
6252sub parse_includes($$)
6253{
6254 my ($Content, $Path) = @_;
6255 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006256 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006257 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006258 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006259 my $Method = substr($Header, 0, 1, "");
6260 substr($Header, length($Header)-1, 1, "");
6261 $Header = path_format($Header, $OSgroup);
6262 if($Method eq "\"" or is_abs($Header))
6263 {
6264 if(-e join_P(get_dirname($Path), $Header))
6265 { # relative path exists
6266 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006267 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006268 else
6269 { # include "..." that doesn't exist is equal to include <...>
6270 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006272 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006273 else {
6274 $Includes{$Header} = 1;
6275 }
6276 }
6277 if($ExtraInfo)
6278 {
6279 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6280 { # FT_FREETYPE_H
6281 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006282 }
6283 }
6284 return \%Includes;
6285}
6286
6287sub ignore_path($)
6288{
6289 my $Path = $_[0];
6290 if($Path=~/\~\Z/)
6291 {# skipping system backup files
6292 return 1;
6293 }
6294 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6295 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6296 return 1;
6297 }
6298 return 0;
6299}
6300
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006301sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006302{
6303 my ($ArrRef, $W) = @_;
6304 return if(length($W)<2);
6305 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6306}
6307
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006308sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006309{
6310 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006312 $H1=~s/\.[a-z]+\Z//ig;
6313 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006314
6315 my $Hname1 = get_filename($H1);
6316 my $Hname2 = get_filename($H2);
6317 my $HDir1 = get_dirname($H1);
6318 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006319 my $Dirname1 = get_filename($HDir1);
6320 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006321
6322 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6323 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6324
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006325 if($_[0] eq $_[1]
6326 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006327 return 0;
6328 }
6329 elsif($H1=~/\A\Q$H2\E/) {
6330 return 1;
6331 }
6332 elsif($H2=~/\A\Q$H1\E/) {
6333 return -1;
6334 }
6335 elsif($HDir1=~/\Q$Hname1\E/i
6336 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 return -1;
6339 }
6340 elsif($HDir2=~/\Q$Hname2\E/i
6341 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006342 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 return 1;
6344 }
6345 elsif($Hname1=~/\Q$Dirname1\E/i
6346 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006347 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006348 return -1;
6349 }
6350 elsif($Hname2=~/\Q$Dirname2\E/i
6351 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006352 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 return 1;
6354 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006355 elsif($Hname1=~/(config|lib|util)/i
6356 and $Hname2!~/(config|lib|util)/i)
6357 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006358 return -1;
6359 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006360 elsif($Hname2=~/(config|lib|util)/i
6361 and $Hname1!~/(config|lib|util)/i)
6362 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006363 return 1;
6364 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006365 else
6366 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006367 my $R1 = checkRelevance($H1);
6368 my $R2 = checkRelevance($H2);
6369 if($R1 and not $R2)
6370 { # libebook/e-book.h
6371 return -1;
6372 }
6373 elsif($R2 and not $R1)
6374 { # libebook/e-book.h
6375 return 1;
6376 }
6377 else
6378 {
6379 return (lc($H1) cmp lc($H2));
6380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 }
6382}
6383
6384sub searchForHeaders($)
6385{
6386 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006388 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006389 registerGccHeaders();
6390
6391 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6392 { # c++ standard include paths
6393 registerCppHeaders();
6394 }
6395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006396 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006397 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6398 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 {
6400 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006401 if($SystemRoot)
6402 {
6403 if(is_abs($Path)) {
6404 $Path = $SystemRoot.$Path;
6405 }
6406 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006407 if(not -e $Path) {
6408 exitStatus("Access_Error", "can't access \'$Path\'");
6409 }
6410 elsif(-f $Path) {
6411 exitStatus("Access_Error", "\'$Path\' - not a directory");
6412 }
6413 elsif(-d $Path)
6414 {
6415 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006416 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006417 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6418 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006419 }
6420 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006421 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 }
6423 }
6424 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006425 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006426 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6427 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006429 # registering directories
6430 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6431 {
6432 next if(not -e $Path);
6433 $Path = get_abs_path($Path);
6434 $Path = path_format($Path, $OSgroup);
6435 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006436 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 }
6438 elsif(-f $Path)
6439 {
6440 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006441 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006442 and not $LocalIncludes{$Dir})
6443 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006444 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006445 # if(my $OutDir = get_dirname($Dir))
6446 # { # registering the outer directory
6447 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6448 # and not $LocalIncludes{$OutDir}) {
6449 # registerDir($OutDir, 0, $LibVersion);
6450 # }
6451 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006452 }
6453 }
6454 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006455
6456 # clean memory
6457 %RegisteredDirs = ();
6458
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006459 # registering headers
6460 my $Position = 0;
6461 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6462 {
6463 if(is_abs($Dest) and not -e $Dest) {
6464 exitStatus("Access_Error", "can't access \'$Dest\'");
6465 }
6466 $Dest = path_format($Dest, $OSgroup);
6467 if(is_header($Dest, 1, $LibVersion))
6468 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006469 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6471 }
6472 }
6473 elsif(-d $Dest)
6474 {
6475 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006476 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006477 {
6478 next if(ignore_path($Path));
6479 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006480 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006481 push(@Registered, $HPath);
6482 }
6483 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006484 @Registered = sort {sortHeaders($a, $b)} @Registered;
6485 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006486 foreach my $Path (@Registered) {
6487 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6488 }
6489 }
6490 else {
6491 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6492 }
6493 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006494
6495 if(defined $Tolerance and $Tolerance=~/4/)
6496 { # 4 - skip headers included by others
6497 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6498 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006499 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006500 delete($Registered_Headers{$LibVersion}{$Path});
6501 }
6502 }
6503 }
6504
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006505 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6506 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006507 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006508 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006509 if(is_abs($Header) and not -f $Header) {
6510 exitStatus("Access_Error", "can't access file \'$Header\'");
6511 }
6512 $Header = path_format($Header, $OSgroup);
6513 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6514 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006515 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006516 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006517 }
6518 else {
6519 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006521 }
6522 }
6523 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6524 { # set relative paths (for duplicates)
6525 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6526 { # search for duplicates
6527 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6528 my $Prefix = get_dirname($FirstPath);
6529 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6530 { # detect a shortest distinguishing prefix
6531 my $NewPrefix = $1;
6532 my %Identity = ();
6533 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6534 {
6535 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6536 $Identity{$Path} = $1;
6537 }
6538 }
6539 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006540 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006541 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6542 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6543 }
6544 last;
6545 }
6546 $Prefix = $NewPrefix; # increase prefix
6547 }
6548 }
6549 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006550
6551 # clean memory
6552 %HeaderName_Paths = ();
6553
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006554 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6555 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006556 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006557 my ($Pos, $PairPos) = (-1, -1);
6558 my ($Path, $PairPath) = ();
6559 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6560 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6561 foreach my $Header_Path (@Paths)
6562 {
6563 if(get_filename($Header_Path) eq $PairName)
6564 {
6565 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6566 $PairPath = $Header_Path;
6567 }
6568 if(get_filename($Header_Path) eq $HeaderName)
6569 {
6570 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6571 $Path = $Header_Path;
6572 }
6573 }
6574 if($PairPos!=-1 and $Pos!=-1
6575 and int($PairPos)<int($Pos))
6576 {
6577 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6578 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6579 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6580 }
6581 }
6582 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6583 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6584 }
6585}
6586
6587sub detect_real_includes($$)
6588{
6589 my ($AbsPath, $LibVersion) = @_;
6590 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6591 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6592 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6593 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6594 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006595 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006597 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6598 return () if(not $Path);
6599 open(PREPROC, $Path);
6600 while(<PREPROC>)
6601 {
6602 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6603 {
6604 my $Include = path_format($1, $OSgroup);
6605 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6606 next;
6607 }
6608 if($Include eq $AbsPath) {
6609 next;
6610 }
6611 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6612 }
6613 }
6614 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006615 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6616}
6617
6618sub detect_header_includes($$)
6619{
6620 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006621 return if(not $LibVersion or not $Path);
6622 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6623 return;
6624 }
6625 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6626
6627 if(not -e $Path) {
6628 return;
6629 }
6630
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006631 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006632 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6633 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006634 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006635 {
6636 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006637 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006638 }
6639 if($RedirectPath ne $Path) {
6640 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6641 }
6642 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006643 else
6644 { # can't find
6645 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006647 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006648 if(my $Inc = parse_includes($Content, $Path))
6649 {
6650 foreach my $Include (keys(%{$Inc}))
6651 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006652 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006653
6654 if(defined $Tolerance and $Tolerance=~/4/)
6655 {
6656 if(my $HPath = identifyHeader($Include, $LibVersion))
6657 {
6658 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6659 }
6660 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006663}
6664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006665sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006666{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 my $Path = $_[0];
6668 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006669 if($OStarget eq "symbian")
6670 {
6671 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6672 { # epoc32/include/libc/{stdio, ...}.h
6673 return 1;
6674 }
6675 }
6676 else
6677 {
6678 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6679 { # /usr/include/{stdio, ...}.h
6680 return 1;
6681 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006683 return 0;
6684}
6685
6686sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006687{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006688 my $Dir = $_[0];
6689 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006690 if($OStarget eq "symbian")
6691 {
6692 if(get_filename($OutDir) eq "libc"
6693 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6694 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6695 return 1;
6696 }
6697 }
6698 else
6699 { # linux
6700 if($OutDir eq "/usr/include"
6701 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6702 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6703 return 1;
6704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006705 }
6706 return 0;
6707}
6708
6709sub detect_recursive_includes($$)
6710{
6711 my ($AbsPath, $LibVersion) = @_;
6712 return () if(not $AbsPath);
6713 if(isCyclical(\@RecurInclude, $AbsPath)) {
6714 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6715 }
6716 my ($AbsDir, $Name) = separate_path($AbsPath);
6717 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006718 { # system GLIBC internals
6719 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006720 }
6721 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6722 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6723 }
6724 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006725
6726 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6727 { # skip /usr/include/c++/*/ headers
6728 return () if(not $ExtraInfo);
6729 }
6730
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006732 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006733 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734 { # check "real" (non-"model") include paths
6735 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6736 pop(@RecurInclude);
6737 return @Paths;
6738 }
6739 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6740 detect_header_includes($AbsPath, $LibVersion);
6741 }
6742 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6743 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006744 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006745 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006746 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006747 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006748 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006750 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 }
6752 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006753 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006754 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006755 { # search for the nearest header
6756 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006757 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006758 if(-f $Candidate) {
6759 $HPath = $Candidate;
6760 }
6761 }
6762 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006763 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006764 }
6765 next if(not $HPath);
6766 if($HPath eq $AbsPath) {
6767 next;
6768 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006769
6770 if($Debug)
6771 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006772# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6773# {
6774# print STDERR "$AbsPath -> $HPath\n";
6775# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006776 }
6777
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006778 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6779 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006780 { # only include <...>, skip include "..." prefixes
6781 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6782 }
6783 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6784 {
6785 if($IncPath eq $AbsPath) {
6786 next;
6787 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006788 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6789 if($RIncType==-1)
6790 { # include "..."
6791 $RIncType = $IncType;
6792 }
6793 elsif($RIncType==2)
6794 {
6795 if($IncType!=-1) {
6796 $RIncType = $IncType;
6797 }
6798 }
6799 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006800 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6801 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6802 }
6803 }
6804 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6805 {
6806 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6807 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6808 { # distinguish math.h from glibc and math.h from the tested library
6809 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6810 last;
6811 }
6812 }
6813 }
6814 pop(@RecurInclude);
6815 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6816}
6817
6818sub find_in_framework($$$)
6819{
6820 my ($Header, $Framework, $LibVersion) = @_;
6821 return "" if(not $Header or not $Framework or not $LibVersion);
6822 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6823 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6824 }
6825 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6826 {
6827 if(get_filename($Dependency) eq $Framework
6828 and -f get_dirname($Dependency)."/".$Header) {
6829 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6830 }
6831 }
6832 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6833}
6834
6835sub find_in_defaults($)
6836{
6837 my $Header = $_[0];
6838 return "" if(not $Header);
6839 if(defined $Cache{"find_in_defaults"}{$Header}) {
6840 return $Cache{"find_in_defaults"}{$Header};
6841 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006842 foreach my $Dir (@DefaultIncPaths,
6843 @DefaultGccPaths,
6844 @DefaultCppPaths,
6845 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006846 {
6847 next if(not $Dir);
6848 if(-f $Dir."/".$Header) {
6849 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6850 }
6851 }
6852 return ($Cache{"find_in_defaults"}{$Header}="");
6853}
6854
6855sub cmp_paths($$)
6856{
6857 my ($Path1, $Path2) = @_;
6858 my @Parts1 = split(/[\/\\]/, $Path1);
6859 my @Parts2 = split(/[\/\\]/, $Path2);
6860 foreach my $Num (0 .. $#Parts1)
6861 {
6862 my $Part1 = $Parts1[$Num];
6863 my $Part2 = $Parts2[$Num];
6864 if($GlibcDir{$Part1}
6865 and not $GlibcDir{$Part2}) {
6866 return 1;
6867 }
6868 elsif($GlibcDir{$Part2}
6869 and not $GlibcDir{$Part1}) {
6870 return -1;
6871 }
6872 elsif($Part1=~/glib/
6873 and $Part2!~/glib/) {
6874 return 1;
6875 }
6876 elsif($Part1!~/glib/
6877 and $Part2=~/glib/) {
6878 return -1;
6879 }
6880 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6881 return $CmpRes;
6882 }
6883 }
6884 return 0;
6885}
6886
6887sub checkRelevance($)
6888{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006889 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006890 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006891
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006892 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006893 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006894 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006895
6896 my $Name = lc(get_filename($Path));
6897 my $Dir = lc(get_dirname($Path));
6898
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006899 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006900
6901 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006902 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006903 my $Len = length($Token);
6904 next if($Len<=1);
6905 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6906 { # include/evolution-data-server-1.4/libebook/e-book.h
6907 return 1;
6908 }
6909 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006910 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006911 return 1;
6912 }
6913 }
6914 return 0;
6915}
6916
6917sub checkFamily(@)
6918{
6919 my @Paths = @_;
6920 return 1 if($#Paths<=0);
6921 my %Prefix = ();
6922 foreach my $Path (@Paths)
6923 {
6924 if($SystemRoot) {
6925 $Path = cut_path_prefix($Path, $SystemRoot);
6926 }
6927 if(my $Dir = get_dirname($Path))
6928 {
6929 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6930 $Prefix{$Dir} += 1;
6931 $Prefix{get_dirname($Dir)} += 1;
6932 }
6933 }
6934 foreach (sort keys(%Prefix))
6935 {
6936 if(get_depth($_)>=3
6937 and $Prefix{$_}==$#Paths+1) {
6938 return 1;
6939 }
6940 }
6941 return 0;
6942}
6943
6944sub isAcceptable($$$)
6945{
6946 my ($Header, $Candidate, $LibVersion) = @_;
6947 my $HName = get_filename($Header);
6948 if(get_dirname($Header))
6949 { # with prefix
6950 return 1;
6951 }
6952 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6953 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6954 return 1;
6955 }
6956 if(checkRelevance($Candidate))
6957 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6958 return 1;
6959 }
6960 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6961 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6962 # /usr/include/qt4/Qt/qsslconfiguration.h
6963 return 1;
6964 }
6965 if($OStarget eq "symbian")
6966 {
6967 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6968 return 1;
6969 }
6970 }
6971 return 0;
6972}
6973
6974sub isRelevant($$$)
6975{ # disallow to search for "abstract" headers in too deep directories
6976 my ($Header, $Candidate, $LibVersion) = @_;
6977 my $HName = get_filename($Header);
6978 if($OStarget eq "symbian")
6979 {
6980 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6981 return 0;
6982 }
6983 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006984 if($OStarget ne "bsd")
6985 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006986 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6987 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6988 return 0;
6989 }
6990 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006991 if($OStarget ne "windows")
6992 {
6993 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6994 { # skip /usr/include/wine/msvcrt
6995 return 0;
6996 }
6997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006998 if(not get_dirname($Header)
6999 and $Candidate=~/[\/\\]wx[\/\\]/)
7000 { # do NOT search in system /wx/ directory
7001 # for headers without a prefix: sstream.h
7002 return 0;
7003 }
7004 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7005 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7006 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7007 return 0;
7008 }
7009 if($Candidate=~/[\/\\]asm-/
7010 and (my $Arch = getArch($LibVersion)) ne "unknown")
7011 { # arch-specific header files
7012 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7013 {# skip ../asm-arm/ if using x86 architecture
7014 return 0;
7015 }
7016 }
7017 my @Candidates = getSystemHeaders($HName, $LibVersion);
7018 if($#Candidates==1)
7019 { # unique header
7020 return 1;
7021 }
7022 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7023 if($#SCandidates==1)
7024 { # unique name
7025 return 1;
7026 }
7027 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7028 if(get_depth($Candidate)-$SystemDepth>=5)
7029 { # abstract headers in too deep directories
7030 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7031 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7032 return 0;
7033 }
7034 }
7035 if($Header eq "parser.h"
7036 and $Candidate!~/\/libxml2\//)
7037 { # select parser.h from xml2 library
7038 return 0;
7039 }
7040 if(not get_dirname($Header)
7041 and keys(%{$SystemHeaders{$HName}})>=3)
7042 { # many headers with the same name
7043 # like thread.h included without a prefix
7044 if(not checkFamily(@Candidates)) {
7045 return 0;
7046 }
7047 }
7048 return 1;
7049}
7050
7051sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007052{ # cache function
7053 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7054 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7055 }
7056 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7057}
7058
7059sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007060{
7061 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007062 if(-f $Header) {
7063 return $Header;
7064 }
7065 if(is_abs($Header) and not -f $Header)
7066 { # incorrect absolute path
7067 return "";
7068 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007069 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007070 { # too abstract configuration headers
7071 return "";
7072 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007073 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007074 if($OSgroup ne "windows")
7075 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007076 if(defined $WinHeaders{lc($HName)}
7077 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007078 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007079 return "";
7080 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007081 }
7082 if($OSgroup ne "macos")
7083 {
7084 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007085 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007086 return "";
7087 }
7088 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007089
7090 if(defined $ObsoleteHeaders{$HName})
7091 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007092 return "";
7093 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007094 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7095 {
7096 if(defined $AlienHeaders{$HName}
7097 or defined $AlienHeaders{$Header})
7098 { # alien headers from other systems
7099 return "";
7100 }
7101 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007102
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007103 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007104 { # search in default paths
7105 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007106 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007107 }
7108 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007109 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007110 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007111 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007112 }
7113 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7114 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7115 {
7116 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007117 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007118 }
7119 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007120 # error
7121 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007122}
7123
7124sub getSystemHeaders($$)
7125{
7126 my ($Header, $LibVersion) = @_;
7127 my @Candidates = ();
7128 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7129 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007130 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007131 next;
7132 }
7133 push(@Candidates, $Candidate);
7134 }
7135 return @Candidates;
7136}
7137
7138sub cut_path_prefix($$)
7139{
7140 my ($Path, $Prefix) = @_;
7141 return $Path if(not $Prefix);
7142 $Prefix=~s/[\/\\]+\Z//;
7143 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7144 return $Path;
7145}
7146
7147sub is_default_include_dir($)
7148{
7149 my $Dir = $_[0];
7150 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007151 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007152}
7153
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007154sub identifyHeader($$)
7155{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007156 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007157 if(not $Header) {
7158 return "";
7159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007160 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7162 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007164 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007165}
7166
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007167sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168{ # search for header by absolute path, relative path or name
7169 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 if(-f $Header)
7171 { # it's relative or absolute path
7172 return get_abs_path($Header);
7173 }
7174 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7175 and my $HeaderDir = find_in_defaults($Header))
7176 { # search for libc headers in the /usr/include
7177 # for non-libc target library before searching
7178 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007179 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007180 }
7181 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7182 { # search in the target library paths
7183 return $Path;
7184 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007185 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007186 { # search in the internal GCC include paths
7187 return $DefaultGccHeader{$Header};
7188 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007189 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007190 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007191 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007192 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007193 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 { # search in the default G++ include paths
7195 return $DefaultCppHeader{$Header};
7196 }
7197 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7198 { # search everywhere in the system
7199 return $AnyPath;
7200 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007201 elsif($OSgroup eq "macos")
7202 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7203 if(my $Dir = get_dirname($Header))
7204 {
7205 my $RelPath = "Headers\/".get_filename($Header);
7206 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007207 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007208 }
7209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007210 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007211 # cannot find anything
7212 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007213}
7214
7215sub getLocation($)
7216{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007217 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7218 {
7219 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007220 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007222 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007223 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224}
7225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007226sub getNameByInfo($)
7227{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007228 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007229 {
7230 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7231 {
7232 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7233 {
7234 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7235 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007236 my $Str = $1;
7237 if($CppMode{$Version}
7238 and $Str=~/\Ac99_(.+)\Z/)
7239 {
7240 if($CppKeywords_A{$1}) {
7241 $Str=$1;
7242 }
7243 }
7244 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007245 }
7246 }
7247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007248 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007249 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250}
7251
7252sub getTreeStr($)
7253{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007254 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007256 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7257 {
7258 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007259 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007260 and $Str=~/\Ac99_(.+)\Z/)
7261 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007262 if($CppKeywords_A{$1}) {
7263 $Str=$1;
7264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007266 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007268 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007269 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007270}
7271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007272sub getFuncShortName($)
7273{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007274 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007275 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007276 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007277 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007278 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007279 {
7280 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7281 {
7282 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7283 return "operator ".$RName;
7284 }
7285 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007286 }
7287 else
7288 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007289 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7290 {
7291 if(my $Ind = $Operator_Indication{$1}) {
7292 return "operator".$Ind;
7293 }
7294 elsif(not $UnknownOperator{$1})
7295 {
7296 printMsg("WARNING", "unknown operator $1");
7297 $UnknownOperator{$1} = 1;
7298 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007299 }
7300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007301 }
7302 else
7303 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007304 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7305 return getTreeStr($1);
7306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307 }
7308 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007309 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007310}
7311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312sub getFuncReturn($)
7313{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007314 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7315 {
7316 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7317 {
7318 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7319 return $1;
7320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 }
7322 }
7323 return "";
7324}
7325
7326sub getFuncOrig($)
7327{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007328 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7329 {
7330 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7331 return $1;
7332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007333 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007334 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007335}
7336
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007337sub unmangleArray(@)
7338{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007339 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007340 { # MSVC mangling
7341 my $UndNameCmd = get_CmdPath("undname");
7342 if(not $UndNameCmd) {
7343 exitStatus("Not_Found", "can't find \"undname\"");
7344 }
7345 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007346 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 }
7348 else
7349 { # GCC mangling
7350 my $CppFiltCmd = get_CmdPath("c++filt");
7351 if(not $CppFiltCmd) {
7352 exitStatus("Not_Found", "can't find c++filt in PATH");
7353 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007354 if(not defined $CPPFILT_SUPPORT_FILE)
7355 {
7356 my $Info = `$CppFiltCmd -h 2>&1`;
7357 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7358 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007359 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007360 if($CPPFILT_SUPPORT_FILE)
7361 { # new versions of c++filt can take a file
7362 if($#_>$MAX_CPPFILT_FILE_SIZE)
7363 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7364 # this is fixed in the oncoming version of Binutils
7365 my @Half = splice(@_, 0, ($#_+1)/2);
7366 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007368 else
7369 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007370 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7371 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7372 if($?==139)
7373 { # segmentation fault
7374 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7375 }
7376 return split(/\n/, $Res);
7377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378 }
7379 else
7380 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007381 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7382 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007383 my @Half = splice(@_, 0, ($#_+1)/2);
7384 return (unmangleArray(@Half), unmangleArray(@_))
7385 }
7386 else
7387 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007389 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7390 if($?==139)
7391 { # segmentation fault
7392 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7393 }
7394 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007395 }
7396 }
7397 }
7398}
7399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400sub get_ChargeLevel($$)
7401{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007402 my ($Symbol, $LibVersion) = @_;
7403 return "" if($Symbol!~/\A(_Z|\?)/);
7404 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7405 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007407 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007408 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[in-charge]";
7411 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007412 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 return "[not-in-charge]";
7414 }
7415 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007416 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007417 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007418 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 return "[in-charge]";
7420 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007421 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422 return "[not-in-charge]";
7423 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007424 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007425 return "[in-charge-deleting]";
7426 }
7427 }
7428 }
7429 else
7430 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007431 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007432 return "[in-charge]";
7433 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007434 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435 return "[not-in-charge]";
7436 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007437 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007438 return "[in-charge]";
7439 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007440 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441 return "[not-in-charge]";
7442 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007443 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 return "[in-charge-deleting]";
7445 }
7446 }
7447 return "";
7448}
7449
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007450sub get_Signature_M($$)
7451{
7452 my ($Symbol, $LibVersion) = @_;
7453 my $Signature_M = $tr_name{$Symbol};
7454 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7455 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007456 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007457 }
7458 return $Signature_M;
7459}
7460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461sub get_Signature($$)
7462{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007463 my ($Symbol, $LibVersion) = @_;
7464 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7465 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007467 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007468 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007469
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007470 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007471
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007472 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007474 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7475 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007476 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7477 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007478
7479 if(index($Symbol, "_ZTV")==0) {
7480 return "vtable for $ClassName [data]";
7481 }
7482
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007483 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007484 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7485 $Signature .= "~";
7486 }
7487 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007489 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007490 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 }
7492 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007493 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007495 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7496 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007497 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007498 else
7499 {
7500 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007501 }
7502 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007503 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007505 if($Pos eq "") {
7506 next;
7507 }
7508
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007509 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007510 if(not $ParamTypeId) {
7511 next;
7512 }
7513
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007514 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 if(not $ParamTypeName) {
7516 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7517 }
7518 foreach my $Typedef (keys(%ChangedTypedef))
7519 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007520 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7521 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007524 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7525 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007526 if($ParamName eq "this"
7527 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007528 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007529 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007530 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007531 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007532 }
7533 else {
7534 push(@ParamArray, $ParamTypeName);
7535 }
7536 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007537 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7538 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007539 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007540 }
7541 else
7542 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007545 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007547 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007548 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7549 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007550 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007551 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007552 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7553 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007554 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7557 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007558 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007559 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007560 }
7561 }
7562 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007563 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007564 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565 }
7566 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007567 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007569 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007570}
7571
7572sub create_member_decl($$)
7573{
7574 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007575 if($TName=~/\([\*]+\)/)
7576 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7578 return $TName;
7579 }
7580 else
7581 {
7582 my @ArraySizes = ();
7583 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7584 push(@ArraySizes, $1);
7585 }
7586 return $TName." ".$Member.join("", @ArraySizes);
7587 }
7588}
7589
7590sub getFuncType($)
7591{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007592 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7593 {
7594 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7595 {
7596 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7597 {
7598 if($Type eq "method_type") {
7599 return "Method";
7600 }
7601 elsif($Type eq "function_type") {
7602 return "Function";
7603 }
7604 else {
7605 return "Other";
7606 }
7607 }
7608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007610 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611}
7612
7613sub getFuncTypeId($)
7614{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007615 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7616 {
7617 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7618 return $1;
7619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007620 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007621 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622}
7623
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007624sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007625{ # "._N" or "$_N" in older GCC versions
7626 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007627}
7628
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007629sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007630{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007631 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7632 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007633 }
7634
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007635 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007636
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007637 if($_[1] ne "S")
7638 {
7639 $N=~s/\A[ ]+//g;
7640 $N=~s/[ ]+\Z//g;
7641 $N=~s/[ ]{2,}/ /g;
7642 }
7643
7644 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007645
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007646 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7647
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007648 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007649
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007650 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7651 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007652
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007653 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007654
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007655 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007656
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007657 if($_[1] eq "S")
7658 {
7659 if(index($N, "operator")!=-1) {
7660 $N=~s/\b(operator[ ]*)> >/$1>>/;
7661 }
7662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007663
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007664 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007665
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007666 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667}
7668
7669sub get_HeaderDeps($$)
7670{
7671 my ($AbsPath, $LibVersion) = @_;
7672 return () if(not $AbsPath or not $LibVersion);
7673 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7674 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7675 }
7676 my %IncDir = ();
7677 detect_recursive_includes($AbsPath, $LibVersion);
7678 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7679 {
7680 next if(not $HeaderPath);
7681 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7682 my $Dir = get_dirname($HeaderPath);
7683 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7684 {
7685 my $Dep = $Dir;
7686 if($Prefix)
7687 {
7688 if($OSgroup eq "windows")
7689 { # case insensitive seach on windows
7690 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7691 next;
7692 }
7693 }
7694 elsif($OSgroup eq "macos")
7695 { # seach in frameworks
7696 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7697 {
7698 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7699 {# frameworks
7700 my ($HFramework, $HName) = ($1, $2);
7701 $Dep = $HFramework;
7702 }
7703 else
7704 {# mismatch
7705 next;
7706 }
7707 }
7708 }
7709 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7710 { # Linux, FreeBSD
7711 next;
7712 }
7713 }
7714 if(not $Dep)
7715 { # nothing to include
7716 next;
7717 }
7718 if(is_default_include_dir($Dep))
7719 { # included by the compiler
7720 next;
7721 }
7722 if(get_depth($Dep)==1)
7723 { # too short
7724 next;
7725 }
7726 if(isLibcDir($Dep))
7727 { # do NOT include /usr/include/{sys,bits}
7728 next;
7729 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007730 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007731 }
7732 }
7733 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7734 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7735}
7736
7737sub sortIncPaths($$)
7738{
7739 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007740 if(not $ArrRef or $#{$ArrRef}<0) {
7741 return $ArrRef;
7742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007743 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7744 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007745 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007746 return $ArrRef;
7747}
7748
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007749sub sortDeps($$$)
7750{
7751 if($Header_Dependency{$_[2]}{$_[0]}
7752 and not $Header_Dependency{$_[2]}{$_[1]}) {
7753 return 1;
7754 }
7755 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7756 and $Header_Dependency{$_[2]}{$_[1]}) {
7757 return -1;
7758 }
7759 return 0;
7760}
7761
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007762sub join_P($$)
7763{
7764 my $S = "/";
7765 if($OSgroup eq "windows") {
7766 $S = "\\";
7767 }
7768 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007769}
7770
7771sub get_namespace_additions($)
7772{
7773 my $NameSpaces = $_[0];
7774 my ($Additions, $AddNameSpaceId) = ("", 1);
7775 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7776 {
7777 next if($SkipNameSpaces{$Version}{$NS});
7778 next if(not $NS or $NameSpaces->{$NS}==-1);
7779 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7780 next if($NS=~/\A__/i);
7781 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007782 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007783 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7784 my @NS_Parts = split(/::/, $NS);
7785 next if($#NS_Parts==-1);
7786 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7787 foreach my $NS_Part (@NS_Parts)
7788 {
7789 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7790 $TypeDecl_Suffix .= "}";
7791 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007792 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007793 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7794 $Additions.=" $TypeDecl\n $FuncDecl\n";
7795 $AddNameSpaceId+=1;
7796 }
7797 return $Additions;
7798}
7799
7800sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007801{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007802 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007803 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007804 if($Fmt eq "windows")
7805 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007806 $Path=~s/\//\\/g;
7807 $Path=lc($Path);
7808 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007809 else
7810 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007811 $Path=~s/\\/\//g;
7812 }
7813 return $Path;
7814}
7815
7816sub inc_opt($$)
7817{
7818 my ($Path, $Style) = @_;
7819 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007820 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007821 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007822 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007823 return "-I\"".path_format($Path, "unix")."\"";
7824 }
7825 elsif($OSgroup eq "macos"
7826 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007827 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007828 return "-F".esc(get_dirname($Path));
7829 }
7830 else {
7831 return "-I".esc($Path);
7832 }
7833 }
7834 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007835 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836 }
7837 return "";
7838}
7839
7840sub platformSpecs($)
7841{
7842 my $LibVersion = $_[0];
7843 my $Arch = getArch($LibVersion);
7844 if($OStarget eq "symbian")
7845 { # options for GCCE compiler
7846 my %Symbian_Opts = map {$_=>1} (
7847 "-D__GCCE__",
7848 "-DUNICODE",
7849 "-fexceptions",
7850 "-D__SYMBIAN32__",
7851 "-D__MARM_INTERWORK__",
7852 "-D_UNICODE",
7853 "-D__S60_50__",
7854 "-D__S60_3X__",
7855 "-D__SERIES60_3X__",
7856 "-D__EPOC32__",
7857 "-D__MARM__",
7858 "-D__EABI__",
7859 "-D__MARM_ARMV5__",
7860 "-D__SUPPORT_CPP_EXCEPTIONS__",
7861 "-march=armv5t",
7862 "-mapcs",
7863 "-mthumb-interwork",
7864 "-DEKA2",
7865 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7866 );
7867 return join(" ", keys(%Symbian_Opts));
7868 }
7869 elsif($OSgroup eq "windows"
7870 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7871 { # add options to MinGW compiler
7872 # to simulate the MSVC compiler
7873 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007874 "-D__unaligned=\" \"",
7875 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007876 "-D_WIN32",
7877 "-D_STDCALL_SUPPORTED",
7878 "-D__int64=\"long long\"",
7879 "-D__int32=int",
7880 "-D__int16=short",
7881 "-D__int8=char",
7882 "-D__possibly_notnullterminated=\" \"",
7883 "-D__nullterminated=\" \"",
7884 "-D__nullnullterminated=\" \"",
7885 "-D__w64=\" \"",
7886 "-D__ptr32=\" \"",
7887 "-D__ptr64=\" \"",
7888 "-D__forceinline=inline",
7889 "-D__inline=inline",
7890 "-D__uuidof(x)=IID()",
7891 "-D__try=",
7892 "-D__except(x)=",
7893 "-D__declspec(x)=__attribute__((x))",
7894 "-D__pragma(x)=",
7895 "-D_inline=inline",
7896 "-D__forceinline=__inline",
7897 "-D__stdcall=__attribute__((__stdcall__))",
7898 "-D__cdecl=__attribute__((__cdecl__))",
7899 "-D__fastcall=__attribute__((__fastcall__))",
7900 "-D__thiscall=__attribute__((__thiscall__))",
7901 "-D_stdcall=__attribute__((__stdcall__))",
7902 "-D_cdecl=__attribute__((__cdecl__))",
7903 "-D_fastcall=__attribute__((__fastcall__))",
7904 "-D_thiscall=__attribute__((__thiscall__))",
7905 "-DSHSTDAPI_(x)=x",
7906 "-D_MSC_EXTENSIONS",
7907 "-DSECURITY_WIN32",
7908 "-D_MSC_VER=1500",
7909 "-D_USE_DECLSPECS_FOR_SAL",
7910 "-D__noop=\" \"",
7911 "-DDECLSPEC_DEPRECATED=\" \"",
7912 "-D__builtin_alignof(x)=__alignof__(x)",
7913 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007914 if($Arch eq "x86")
7915 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007916 $MinGW_Opts{"-D_M_IX86=300"}=1;
7917 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007918 elsif($Arch eq "x86_64")
7919 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007920 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007921 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007922 }
7923 elsif($Arch eq "ia64") {
7924 $MinGW_Opts{"-D_M_IA64=300"}=1;
7925 }
7926 return join(" ", keys(%MinGW_Opts));
7927 }
7928 return "";
7929}
7930
7931my %C_Structure = map {$_=>1} (
7932# FIXME: Can't separate union and struct data types before dumping,
7933# so it sometimes cause compilation errors for unknown reason
7934# when trying to declare TYPE* tmp_add_class_N
7935# This is a list of such structures + list of other C structures
7936 "sigval",
7937 "sigevent",
7938 "sigaction",
7939 "sigvec",
7940 "sigstack",
7941 "timeval",
7942 "timezone",
7943 "rusage",
7944 "rlimit",
7945 "wait",
7946 "flock",
7947 "stat",
7948 "_stat",
7949 "stat32",
7950 "_stat32",
7951 "stat64",
7952 "_stat64",
7953 "_stati64",
7954 "if_nameindex",
7955 "usb_device",
7956 "sigaltstack",
7957 "sysinfo",
7958 "timeLocale",
7959 "tcp_debug",
7960 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007961 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007962 "timespec",
7963 "random_data",
7964 "drand48_data",
7965 "_IO_marker",
7966 "_IO_FILE",
7967 "lconv",
7968 "sched_param",
7969 "tm",
7970 "itimerspec",
7971 "_pthread_cleanup_buffer",
7972 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007973 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007974 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007975 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007976 "sigcontext",
7977 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007978 # Mac
7979 "_timex",
7980 "_class_t",
7981 "_category_t",
7982 "_class_ro_t",
7983 "_protocol_t",
7984 "_message_ref_t",
7985 "_super_message_ref_t",
7986 "_ivar_t",
7987 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007988);
7989
7990sub getCompileCmd($$$)
7991{
7992 my ($Path, $Opt, $Inc) = @_;
7993 my $GccCall = $GCC_PATH;
7994 if($Opt) {
7995 $GccCall .= " ".$Opt;
7996 }
7997 $GccCall .= " -x ";
7998 if($OSgroup eq "macos") {
7999 $GccCall .= "objective-";
8000 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008001
8002 if($EMERGENCY_MODE_48)
8003 { # workaround for GCC 4.8 (C only)
8004 $GccCall .= "c++";
8005 }
8006 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008007 { # compile as "C++" header
8008 # to obtain complete dump using GCC 4.0
8009 $GccCall .= "c++-header";
8010 }
8011 else
8012 { # compile as "C++" source
8013 # GCC 3.3 cannot compile headers
8014 $GccCall .= "c++";
8015 }
8016 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008017 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008018 $GccCall .= " ".$Opts;
8019 }
8020 # allow extra qualifications
8021 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008022 $GccCall .= " -fpermissive";
8023 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008024 if($NoStdInc)
8025 {
8026 $GccCall .= " -nostdinc";
8027 $GccCall .= " -nostdinc++";
8028 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008029 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008030 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008031 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008032 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008033 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008034 if($Inc)
8035 { # include paths
8036 $GccCall .= " ".$Inc;
8037 }
8038 return $GccCall;
8039}
8040
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008041sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008042{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008043 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008044 my %HeaderElems = (
8045 # Types
8046 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008047 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008048 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8049 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008050 "time.h" => ["time_t"],
8051 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008052 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8053 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008054 "stdbool.h" => ["_Bool"],
8055 "rpc/xdr.h" => ["bool_t"],
8056 "in_systm.h" => ["n_long", "n_short"],
8057 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008058 "arpa/inet.h" => ["fw_src", "ip_src"],
8059 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008060 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008061 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008062 );
8063 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008064 foreach (keys(%HeaderElems))
8065 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008066 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008067 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008068 }
8069 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008070 my %Types = ();
8071 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8072 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008073 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008074 }
8075 if(keys(%Types))
8076 {
8077 my %AddHeaders = ();
8078 foreach my $Type (keys(%Types))
8079 {
8080 if(my $Header = $AutoPreamble{$Type})
8081 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008082 if(my $Path = identifyHeader($Header, $LibVersion))
8083 {
8084 if(skipHeader($Path, $LibVersion)) {
8085 next;
8086 }
8087 $Path = path_format($Path, $OSgroup);
8088 $AddHeaders{$Path}{"Type"} = $Type;
8089 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008090 }
8091 }
8092 }
8093 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008094 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008095 }
8096 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008097 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008098}
8099
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008100sub checkCTags($)
8101{
8102 my $Path = $_[0];
8103 if(not $Path) {
8104 return;
8105 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008106 my $CTags = undef;
8107
8108 if($OSgroup eq "bsd")
8109 { # use ectags on BSD
8110 $CTags = get_CmdPath("ectags");
8111 if(not $CTags) {
8112 printMsg("WARNING", "can't find \'ectags\' program");
8113 }
8114 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008115 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008116 $CTags = get_CmdPath("ctags");
8117 }
8118 if(not $CTags)
8119 {
8120 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008121 return;
8122 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008123
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008124 if($OSgroup ne "linux")
8125 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008126 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8127 if($Info!~/exuberant/i)
8128 {
8129 printMsg("WARNING", "incompatible version of \'ctags\' program");
8130 return;
8131 }
8132 }
8133
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008134 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008135 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008136 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008137 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008138 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008139 open(CTAGS, "<", $Out);
8140 while(my $Line = <CTAGS>)
8141 {
8142 chomp($Line);
8143 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008144 if(defined $Intrinsic_Keywords{$Name})
8145 { # noise
8146 next;
8147 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008148 if($Type eq "n")
8149 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008150 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008151 next;
8152 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008153 if(index($Scpe, "struct:")==0) {
8154 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008155 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008156 if(index($Scpe, "namespace:")==0)
8157 {
8158 if($Scpe=~s/\Anamespace://) {
8159 $Name = $Scpe."::".$Name;
8160 }
8161 }
8162 $TUnit_NameSpaces{$Version}{$Name} = 1;
8163 }
8164 elsif($Type eq "p")
8165 {
8166 if(not $Scpe or index($Scpe, "namespace:")==0) {
8167 $TUnit_Funcs{$Version}{$Name} = 1;
8168 }
8169 }
8170 elsif($Type eq "x")
8171 {
8172 if(not $Scpe or index($Scpe, "namespace:")==0) {
8173 $TUnit_Vars{$Version}{$Name} = 1;
8174 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008175 }
8176 }
8177 close(CTAGS);
8178}
8179
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008180sub preChange($$)
8181{
8182 my ($HeaderPath, $IncStr) = @_;
8183
8184 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8185 my $Content = undef;
8186
8187 if($OStarget eq "windows"
8188 and get_dumpmachine($GCC_PATH)=~/mingw/i
8189 and $MinGWMode{$Version}!=-1)
8190 { # modify headers to compile by MinGW
8191 if(not $Content)
8192 { # preprocessing
8193 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8194 }
8195 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8196 { # __asm { ... }
8197 $MinGWMode{$Version}=1;
8198 }
8199 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8200 { # comments after preprocessing
8201 $MinGWMode{$Version}=1;
8202 }
8203 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8204 { # 0xffui8
8205 $MinGWMode{$Version}=1;
8206 }
8207
8208 if($MinGWMode{$Version}) {
8209 printMsg("INFO", "Using MinGW compatibility mode");
8210 }
8211 }
8212
8213 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8214 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8215 { # rename C++ keywords in C code
8216 # disable this code by -cpp-compatible option
8217 if(not $Content)
8218 { # preprocessing
8219 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8220 }
8221 my $RegExp_C = join("|", keys(%CppKeywords_C));
8222 my $RegExp_F = join("|", keys(%CppKeywords_F));
8223 my $RegExp_O = join("|", keys(%CppKeywords_O));
8224
8225 my $Detected = undef;
8226
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008227 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/$1$2c99_$3$4/g)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008228 { # MATCH:
8229 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008230 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008231 # unsigned private: 8;
8232 # DO NOT MATCH:
8233 # #pragma GCC visibility push(default)
8234 $CppMode{$Version} = 1;
8235 $Detected = "$1$2$3$4" if(not defined $Detected);
8236 }
8237 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8238 { # MATCH:
8239 # int delete(...);
8240 # int explicit(...);
8241 # DO NOT MATCH:
8242 # void operator delete(...)
8243 $CppMode{$Version} = 1;
8244 $Detected = "$1$2$3" if(not defined $Detected);
8245 }
8246 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8247 { # MATCH:
8248 # int bool;
8249 # DO NOT MATCH:
8250 # bool X;
8251 # return *this;
8252 # throw;
8253 $CppMode{$Version} = 1;
8254 $Detected = "$1$2$3" if(not defined $Detected);
8255 }
8256 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8257 { # MATCH:
8258 # int operator(...);
8259 # DO NOT MATCH:
8260 # int operator()(...);
8261 $CppMode{$Version} = 1;
8262 $Detected = "$1$2$3" if(not defined $Detected);
8263 }
8264 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8265 { # MATCH:
8266 # int foo(int operator);
8267 # int foo(int operator, int other);
8268 # DO NOT MATCH:
8269 # int operator,(...);
8270 $CppMode{$Version} = 1;
8271 $Detected = "$1$2$3" if(not defined $Detected);
8272 }
8273 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8274 { # MATCH:
8275 # int foo(gboolean *bool);
8276 # DO NOT MATCH:
8277 # void setTabEnabled(int index, bool);
8278 $CppMode{$Version} = 1;
8279 $Detected = "$1$2$3" if(not defined $Detected);
8280 }
8281 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8282 { # MATCH:
8283 # int foo(int* this);
8284 # int bar(int this);
8285 # int baz(int throw);
8286 # DO NOT MATCH:
8287 # foo(X, this);
8288 $CppMode{$Version} = 1;
8289 $Detected = "$1$2$3$4" if(not defined $Detected);
8290 }
8291 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8292 { # MATCH:
8293 # struct template {...};
8294 # extern template foo(...);
8295 $CppMode{$Version} = 1;
8296 $Detected = "$1$2" if(not defined $Detected);
8297 }
8298
8299 if($CppMode{$Version} == 1)
8300 {
8301 if($Debug)
8302 {
8303 $Detected=~s/\A\s+//g;
8304 printMsg("INFO", "Detected code: \"$Detected\"");
8305 }
8306 }
8307
8308 # remove typedef enum NAME NAME;
8309 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8310 my $N = 0;
8311 while($N<=$#FwdTypedefs-1)
8312 {
8313 my $S = $FwdTypedefs[$N];
8314 if($S eq $FwdTypedefs[$N+1])
8315 {
8316 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008317 $CppMode{$Version} = 1;
8318
8319 if($Debug) {
8320 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8321 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008322 }
8323 $N+=2;
8324 }
8325
8326 if($CppMode{$Version}==1) {
8327 printMsg("INFO", "Using C++ compatibility mode");
8328 }
8329 }
8330
8331 if($CppMode{$Version}==1
8332 or $MinGWMode{$Version}==1)
8333 {
8334 my $IPath = $TMP_DIR."/dump$Version.i";
8335 writeFile($IPath, $Content);
8336 return $IPath;
8337 }
8338
8339 return undef;
8340}
8341
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008342sub getDump()
8343{
8344 if(not $GCC_PATH) {
8345 exitStatus("Error", "internal error - GCC path is not set");
8346 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008347
8348 my @Headers = keys(%{$Registered_Headers{$Version}});
8349 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8350
8351 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8352
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008353 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008354 my $HeaderPath = $TmpHeaderPath;
8355
8356 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008357 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008358 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8359 {
8360 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008361 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008362 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008363 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008364 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8365 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008366 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008367 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008368 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008369 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8370 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008372 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008373 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008374
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008375 if($ExtraInfo)
8376 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008377 if($IncludeString) {
8378 writeFile($ExtraInfo."/include-string", $IncludeString);
8379 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008380 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8381 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008382
8383 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8384 {
8385 my $REDIR = "";
8386 foreach my $P1 (sort @Redirects) {
8387 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8388 }
8389 writeFile($ExtraInfo."/include-redirect", $REDIR);
8390 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008391 }
8392
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008393 if(not keys(%{$TargetHeaders{$Version}}))
8394 { # Target headers
8395 addTargetHeaders($Version);
8396 }
8397
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008398 # clean memory
8399 %RecursiveIncludes = ();
8400 %Header_Include_Prefix = ();
8401 %Header_Includes = ();
8402
8403 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008404 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008405 delete($Cache{"detect_header_includes"});
8406 delete($Cache{"selectSystemHeader"});
8407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008408 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008409 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8410 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008411
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008412 if($ExtraInfo)
8413 { # extra information for other tools
8414 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8415 }
8416
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008417 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008418 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008419 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008420
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008421 if($COMMON_LANGUAGE{$Version} eq "C++") {
8422 checkCTags($Pre);
8423 }
8424
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008425 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8426 { # try to correct the preprocessor output
8427 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008428 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008430 if($COMMON_LANGUAGE{$Version} eq "C++")
8431 { # add classes and namespaces to the dump
8432 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008433 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008434 or $MinGWMode{$Version}==1) {
8435 $CHdump .= " -fpreprocessed";
8436 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008437 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008439 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008440 chdir($ORIG_DIR);
8441 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8442 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008443 my $Content = readFile($ClassDump);
8444 foreach my $ClassInfo (split(/\n\n/, $Content))
8445 {
8446 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8447 {
8448 my $CName = $1;
8449 next if($CName=~/\A(__|_objc_|_opaque_)/);
8450 $TUnit_NameSpaces{$Version}{$CName} = -1;
8451 if($CName=~/\A[\w:]+\Z/)
8452 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008453 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008454 }
8455 if($CName=~/(\w[\w:]*)::/)
8456 { # namespaces
8457 my $NS = $1;
8458 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8459 $TUnit_NameSpaces{$Version}{$NS} = 1;
8460 }
8461 }
8462 }
8463 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8464 { # read v-tables (advanced approach)
8465 my ($CName, $VTable) = ($1, $2);
8466 $ClassVTable_Content{$Version}{$CName} = $VTable;
8467 }
8468 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008469 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8470 { # add user-defined namespaces
8471 $TUnit_NameSpaces{$Version}{$NS} = 1;
8472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008473 if($Debug)
8474 { # debug mode
8475 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008476 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008477 }
8478 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008479 }
8480
8481 # add namespaces and classes
8482 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8483 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008484 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008485 }
8486 # some GCC versions don't include class methods to the TU dump by default
8487 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008488 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008489 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8490 {
8491 next if($C_Structure{$CName});
8492 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008493 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008494 if(not $Force and $GCC_44
8495 and $OSgroup eq "linux")
8496 { # optimization for linux with GCC >= 4.4
8497 # disable this code by -force option
8498 if(index($CName, "::")!=-1)
8499 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008500 next;
8501 }
8502 }
8503 else
8504 {
8505 if($CName=~/\A(.+)::[^:]+\Z/
8506 and $TUnit_Classes{$Version}{$1})
8507 { # classes inside other classes
8508 next;
8509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008511 if(defined $TUnit_Funcs{$Version}{$CName})
8512 { # the same name for a function and type
8513 next;
8514 }
8515 if(defined $TUnit_Vars{$Version}{$CName})
8516 { # the same name for a variable and type
8517 next;
8518 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008519 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8520 }
8521 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008522 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 }
8524 }
8525 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8526 # create TU dump
8527 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008528 if($UserLang eq "C") {
8529 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8530 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008531 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008532 or $MinGWMode{$Version}==1) {
8533 $TUdump .= " -fpreprocessed";
8534 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008535 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008536 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8537 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008538 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008539 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008540 if($?)
8541 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008542 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008543 { # try to recompile
8544 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008545 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008546 and index($Errors, "c99_")!=-1
8547 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008548 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008549 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008550
8551 if($Debug)
8552 {
8553 # printMsg("INFO", $Errors);
8554 }
8555
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008556 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008557 resetLogging($Version);
8558 $TMP_DIR = tempdir(CLEANUP=>1);
8559 return getDump();
8560 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008561 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008562 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008563 { # add auto preamble headers and try again
8564 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008565 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008566 foreach my $Num (0 .. $#Headers)
8567 {
8568 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008569 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8570 {
8571 push_U($Include_Preamble{$Version}, $Path);
8572 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008573 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008574 }
8575 resetLogging($Version);
8576 $TMP_DIR = tempdir(CLEANUP=>1);
8577 return getDump();
8578 }
8579 elsif($Cpp0xMode{$Version}!=-1
8580 and ($Errors=~/\Q-std=c++0x\E/
8581 or $Errors=~/is not a class or namespace/))
8582 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008583 if(check_gcc($GCC_PATH, "4.6"))
8584 {
8585 $Cpp0xMode{$Version}=-1;
8586 printMsg("INFO", "Enabling c++0x mode");
8587 resetLogging($Version);
8588 $TMP_DIR = tempdir(CLEANUP=>1);
8589 $CompilerOptions{$Version} .= " -std=c++0x";
8590 return getDump();
8591 }
8592 else {
8593 printMsg("WARNING", "Probably c++0x construction detected");
8594 }
8595
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008596 }
8597 elsif($MinGWMode{$Version}==1)
8598 { # disable MinGW mode and try again
8599 $MinGWMode{$Version}=-1;
8600 resetLogging($Version);
8601 $TMP_DIR = tempdir(CLEANUP=>1);
8602 return getDump();
8603 }
8604 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008605 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008606 else {
8607 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008609 printMsg("ERROR", "some errors occurred when compiling headers");
8610 printErrorLog($Version);
8611 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008612 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008613 }
8614 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008615 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008616 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008617
8618 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8619 return $TUs[0];
8620 }
8621 else
8622 {
8623 my $Msg = "can't compile header(s)";
8624 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8625 $Msg .= "\nDid you install G++?";
8626 }
8627 exitStatus("Cannot_Compile", $Msg);
8628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008629}
8630
8631sub cmd_file($)
8632{
8633 my $Path = $_[0];
8634 return "" if(not $Path or not -e $Path);
8635 if(my $CmdPath = get_CmdPath("file")) {
8636 return `$CmdPath -b \"$Path\"`;
8637 }
8638 return "";
8639}
8640
8641sub getIncString($$)
8642{
8643 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008644 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008645 my $String = "";
8646 foreach (@{$ArrRef}) {
8647 $String .= " ".inc_opt($_, $Style);
8648 }
8649 return $String;
8650}
8651
8652sub getIncPaths(@)
8653{
8654 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008655 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656 if($INC_PATH_AUTODETECT{$Version})
8657 { # auto-detecting dependencies
8658 my %Includes = ();
8659 foreach my $HPath (@HeaderPaths)
8660 {
8661 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8662 {
8663 if($Skip_Include_Paths{$Version}{$Dir}) {
8664 next;
8665 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008666 if($SystemRoot)
8667 {
8668 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8669 next;
8670 }
8671 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008672 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 }
8674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008675 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008676 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677 }
8678 }
8679 else
8680 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008681 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008682 }
8683 return \@IncPaths;
8684}
8685
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008686sub push_U($@)
8687{ # push unique
8688 if(my $Array = shift @_)
8689 {
8690 if(@_)
8691 {
8692 my %Exist = map {$_=>1} @{$Array};
8693 foreach my $Elem (@_)
8694 {
8695 if(not defined $Exist{$Elem})
8696 {
8697 push(@{$Array}, $Elem);
8698 $Exist{$Elem} = 1;
8699 }
8700 }
8701 }
8702 }
8703}
8704
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008705sub callPreprocessor($$$)
8706{
8707 my ($Path, $Inc, $LibVersion) = @_;
8708 return "" if(not $Path or not -f $Path);
8709 my $IncludeString=$Inc;
8710 if(not $Inc) {
8711 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8712 }
8713 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008714 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008715 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008716 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008717}
8718
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008719sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720{ # native "find" is much faster than File::Find (~6x)
8721 # also the File::Find doesn't support --maxdepth N option
8722 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008723 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008724 return () if(not $Path or not -e $Path);
8725 if($OSgroup eq "windows")
8726 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008727 $Path = get_abs_path($Path);
8728 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008729 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008730 if($MaxDepth!=1) {
8731 $Cmd .= " /S";
8732 }
8733 if($Type eq "d") {
8734 $Cmd .= " /AD";
8735 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008736 elsif($Type eq "f") {
8737 $Cmd .= " /A-D";
8738 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008739 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008740 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008741 {
8742 if(not $UseRegex)
8743 { # FIXME: how to search file names in MS shell?
8744 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008745 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008746 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008747 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008748 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008749 }
8750 my @AbsPaths = ();
8751 foreach my $File (@Files)
8752 {
8753 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008754 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008755 }
8756 if($Type eq "f" and not -f $File)
8757 { # skip dirs
8758 next;
8759 }
8760 push(@AbsPaths, path_format($File, $OSgroup));
8761 }
8762 if($Type eq "d") {
8763 push(@AbsPaths, $Path);
8764 }
8765 return @AbsPaths;
8766 }
8767 else
8768 {
8769 my $FindCmd = get_CmdPath("find");
8770 if(not $FindCmd) {
8771 exitStatus("Not_Found", "can't find a \"find\" command");
8772 }
8773 $Path = get_abs_path($Path);
8774 if(-d $Path and -l $Path
8775 and $Path!~/\/\Z/)
8776 { # for directories that are symlinks
8777 $Path.="/";
8778 }
8779 my $Cmd = $FindCmd." \"$Path\"";
8780 if($MaxDepth) {
8781 $Cmd .= " -maxdepth $MaxDepth";
8782 }
8783 if($Type) {
8784 $Cmd .= " -type $Type";
8785 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008786 if($Name and not $UseRegex)
8787 { # wildcards
8788 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008789 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008790 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008791 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008792 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8793 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008794 my @Files = split(/\n/, $Res);
8795 if($Name and $UseRegex)
8796 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008797 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008798 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008799 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 }
8801}
8802
8803sub unpackDump($)
8804{
8805 my $Path = $_[0];
8806 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008807
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008808 $Path = get_abs_path($Path);
8809 $Path = path_format($Path, $OSgroup);
8810 my ($Dir, $FileName) = separate_path($Path);
8811 my $UnpackDir = $TMP_DIR."/unpack";
8812 rmtree($UnpackDir);
8813 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008815 if($FileName=~s/\Q.zip\E\Z//g)
8816 { # *.zip
8817 my $UnzipCmd = get_CmdPath("unzip");
8818 if(not $UnzipCmd) {
8819 exitStatus("Not_Found", "can't find \"unzip\" command");
8820 }
8821 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008822 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008823 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008824 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008825 }
8826 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008827 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008828 if(not @Contents) {
8829 exitStatus("Error", "can't extract \'$Path\'");
8830 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008831 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008833 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008834 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008835 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008836 if($OSgroup eq "windows")
8837 { # -xvzf option is not implemented in tar.exe (2003)
8838 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8839 my $TarCmd = get_CmdPath("tar");
8840 if(not $TarCmd) {
8841 exitStatus("Not_Found", "can't find \"tar\" command");
8842 }
8843 my $GzipCmd = get_CmdPath("gzip");
8844 if(not $GzipCmd) {
8845 exitStatus("Not_Found", "can't find \"gzip\" command");
8846 }
8847 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008848 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008849 if($?) {
8850 exitStatus("Error", "can't extract \'$Path\'");
8851 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008852 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008854 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855 }
8856 chdir($ORIG_DIR);
8857 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008858 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008859 if(not @Contents) {
8860 exitStatus("Error", "can't extract \'$Path\'");
8861 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008862 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008863 }
8864 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008865 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008866 my $TarCmd = get_CmdPath("tar");
8867 if(not $TarCmd) {
8868 exitStatus("Not_Found", "can't find \"tar\" command");
8869 }
8870 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008871 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008873 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008874 }
8875 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008876 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008877 if(not @Contents) {
8878 exitStatus("Error", "can't extract \'$Path\'");
8879 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008880 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008881 }
8882 }
8883}
8884
8885sub createArchive($$)
8886{
8887 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008888 if(not $To) {
8889 $To = ".";
8890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008891 if(not $Path or not -e $Path
8892 or not -d $To) {
8893 return "";
8894 }
8895 my ($From, $Name) = separate_path($Path);
8896 if($OSgroup eq "windows")
8897 { # *.zip
8898 my $ZipCmd = get_CmdPath("zip");
8899 if(not $ZipCmd) {
8900 exitStatus("Not_Found", "can't find \"zip\"");
8901 }
8902 my $Pkg = $To."/".$Name.".zip";
8903 unlink($Pkg);
8904 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008905 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008906 if($?)
8907 { # cannot allocate memory (or other problems with "zip")
8908 unlink($Path);
8909 exitStatus("Error", "can't pack the ABI dump: ".$!);
8910 }
8911 chdir($ORIG_DIR);
8912 unlink($Path);
8913 return $Pkg;
8914 }
8915 else
8916 { # *.tar.gz
8917 my $TarCmd = get_CmdPath("tar");
8918 if(not $TarCmd) {
8919 exitStatus("Not_Found", "can't find \"tar\"");
8920 }
8921 my $GzipCmd = get_CmdPath("gzip");
8922 if(not $GzipCmd) {
8923 exitStatus("Not_Found", "can't find \"gzip\"");
8924 }
8925 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8926 unlink($Pkg);
8927 chdir($From);
8928 system($TarCmd, "-czf", $Pkg, $Name);
8929 if($?)
8930 { # cannot allocate memory (or other problems with "tar")
8931 unlink($Path);
8932 exitStatus("Error", "can't pack the ABI dump: ".$!);
8933 }
8934 chdir($ORIG_DIR);
8935 unlink($Path);
8936 return $To."/".$Name.".tar.gz";
8937 }
8938}
8939
8940sub is_header_file($)
8941{
8942 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8943 return $_[0];
8944 }
8945 return 0;
8946}
8947
8948sub is_not_header($)
8949{
8950 if($_[0]=~/\.\w+\Z/
8951 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8952 return 1;
8953 }
8954 return 0;
8955}
8956
8957sub is_header($$$)
8958{
8959 my ($Header, $UserDefined, $LibVersion) = @_;
8960 return 0 if(-d $Header);
8961 if(-f $Header) {
8962 $Header = get_abs_path($Header);
8963 }
8964 else
8965 {
8966 if(is_abs($Header))
8967 { # incorrect absolute path
8968 return 0;
8969 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008970 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008971 $Header = $HPath;
8972 }
8973 else
8974 { # can't find header
8975 return 0;
8976 }
8977 }
8978 if($Header=~/\.\w+\Z/)
8979 { # have an extension
8980 return is_header_file($Header);
8981 }
8982 else
8983 {
8984 if($UserDefined==2)
8985 { # specified on the command line
8986 if(cmd_file($Header)!~/HTML|XML/i) {
8987 return $Header;
8988 }
8989 }
8990 elsif($UserDefined)
8991 { # specified in the XML-descriptor
8992 # header file without an extension
8993 return $Header;
8994 }
8995 else
8996 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008997 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008998 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008999 { # !~/HTML|XML|shared|dynamic/i
9000 return $Header;
9001 }
9002 }
9003 }
9004 return 0;
9005}
9006
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009007sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009008{
9009 my $LibVersion = $_[0];
9010 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9011 {
9012 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009013 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009014
9015 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9016 detect_recursive_includes($RegHeader, $LibVersion);
9017 }
9018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009019 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9020 {
9021 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009022
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009023 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009024 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9025 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009026 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009027 }
9028 }
9029 }
9030}
9031
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009032sub familiarDirs($$)
9033{
9034 my ($D1, $D2) = @_;
9035 if($D1 eq $D2) {
9036 return 1;
9037 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009038
9039 my $U1 = index($D1, "/usr/");
9040 my $U2 = index($D2, "/usr/");
9041
9042 if($U1==0 and $U2!=0) {
9043 return 0;
9044 }
9045
9046 if($U2==0 and $U1!=0) {
9047 return 0;
9048 }
9049
9050 if(index($D2, $D1."/")==0) {
9051 return 1;
9052 }
9053
9054 # /usr/include/DIR
9055 # /home/user/DIR
9056
9057 my $DL = get_depth($D1);
9058
9059 my @Dirs1 = ($D1);
9060 while($DL - get_depth($D1)<=2
9061 and get_depth($D1)>=4
9062 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9063 push(@Dirs1, $D1);
9064 }
9065
9066 my @Dirs2 = ($D2);
9067 while(get_depth($D2)>=4
9068 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9069 push(@Dirs2, $D2);
9070 }
9071
9072 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009073 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009074 foreach my $P2 (@Dirs2)
9075 {
9076
9077 if($P1 eq $P2) {
9078 return 1;
9079 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009080 }
9081 }
9082 return 0;
9083}
9084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009085sub readHeaders($)
9086{
9087 $Version = $_[0];
9088 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9089 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009090 if($Debug)
9091 { # debug mode
9092 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009093 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009094 }
9095 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009096}
9097
9098sub prepareTypes($)
9099{
9100 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009101 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 { # support for old ABI dumps
9103 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009104 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009105 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9107 if($TName=~/\A(\w+)::(\w+)/) {
9108 my ($P1, $P2) = ($1, $2);
9109 if($P1 eq $P2) {
9110 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009112 else {
9113 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009115 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009116 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009117 }
9118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009119 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009120 { # support for old ABI dumps
9121 # V < 2.5: array size == "number of elements"
9122 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009123 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009124 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009125 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009126 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009127 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009128 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009129 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009130 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009131 $Size *= $Base{"Size"};
9132 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009133 }
9134 else
9135 { # array[] is a pointer
9136 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009137 }
9138 }
9139 }
9140 }
9141 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009142 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009143 { # support for old ABI dumps
9144 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009145 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009146 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009147 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009148 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009149 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009150 my %Type = get_Type($TypeId, $LibVersion);
9151 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9152 my %Type2 = get_Type($TypeId_2, $V2);
9153 if($Type{"Size"} ne $Type2{"Size"}) {
9154 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009155 }
9156 }
9157 }
9158 }
9159}
9160
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009161sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009162{
9163 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009164
9165 if(not keys(%{$SymbolInfo{$LibVersion}}))
9166 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009167 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009168 {
9169 if($CheckHeadersOnly) {
9170 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9171 }
9172 else {
9173 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9174 }
9175 }
9176 }
9177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009178 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009179 if(not checkDump(1, "2.10")
9180 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 { # different formats
9182 $Remangle = 1;
9183 }
9184 if($CheckHeadersOnly)
9185 { # different languages
9186 if($UserLang)
9187 { # --lang=LANG for both versions
9188 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9189 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9190 {
9191 if($UserLang eq "C++")
9192 { # remangle symbols
9193 $Remangle = 1;
9194 }
9195 elsif($UserLang eq "C")
9196 { # remove mangling
9197 $Remangle = -1;
9198 }
9199 }
9200 }
9201 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009202
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009203 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009204 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009205 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009206 { # support for old ABI dumps
9207 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9208 {
9209 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9210 {
9211 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9212 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009213 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009214 if(defined $DVal and $DVal ne "")
9215 {
9216 if($TName eq "char") {
9217 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9218 }
9219 elsif($TName eq "bool") {
9220 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9221 }
9222 }
9223 }
9224 }
9225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009226 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009227 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009228 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9229 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009230 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009231 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9232 # + support for old ABI dumps
9233 next;
9234 }
9235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009236 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009237 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009238 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009239 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009240
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009241 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009242 if(not checkDump(1, "2.12")
9243 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009244 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009245 if($ShortName eq "operator>>")
9246 {
9247 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9248 { # corrected mangling of operator>>
9249 $SRemangle = 1;
9250 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009251 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009252 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9253 {
9254 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9255 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9256 { # corrected mangling of const global data
9257 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9258 # and incorrectly mangled by old ACC versions
9259 $SRemangle = 1;
9260 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009261 }
9262 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009263 if(not $CheckHeadersOnly)
9264 { # support for old ABI dumps
9265 if(not checkDump(1, "2.17")
9266 or not checkDump(2, "2.17"))
9267 {
9268 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9269 {
9270 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9271 {
9272 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9273 {
9274 $MnglName = $ShortName;
9275 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9276 }
9277 }
9278 }
9279 }
9280 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009281 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009282 { # support for old ABI dumps: some symbols are not mangled in old dumps
9283 # mangle both sets of symbols (old and new)
9284 # NOTE: remangling all symbols by the same mangler
9285 if($MnglName=~/\A_ZN(V|)K/)
9286 { # mangling may be incorrect on old ABI dumps
9287 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009288 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 }
9290 if($MnglName=~/\A_ZN(K|)V/)
9291 { # mangling may be incorrect on old ABI dumps
9292 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009293 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009294 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009295 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9296 or (not $ClassID and $CheckHeadersOnly)
9297 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9298 { # support for old ABI dumps, GCC >= 4.0
9299 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009300 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009301 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009302 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 $MangledNames{$LibVersion}{$MnglName} = 1;
9304 }
9305 }
9306 }
9307 elsif($Remangle==-1)
9308 { # remove mangling
9309 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009310 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009312 if(not $MnglName) {
9313 next;
9314 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009315
9316 # NOTE: duplicated entries in the ABI Dump
9317 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9318 {
9319 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9320 {
9321 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9322 {
9323 next;
9324 }
9325 }
9326 }
9327
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009328 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9329 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009330 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009332 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009333 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009334 { # support for old dumps
9335 # add "Volatile" attribute
9336 if($MnglName=~/_Z(K|)V/) {
9337 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9338 }
9339 }
9340 # symbol and its symlink have same signatures
9341 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009342 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009343 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009344
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009345 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9346 {
9347 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009348
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009349 if($SymVer{$LibVersion}{$Alias}) {
9350 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9351 }
9352 }
9353
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009354 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009355 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009356 }
9357 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9358 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9359 }
9360 if($ExtendedCheck)
9361 { # --ext option
9362 addExtension($LibVersion);
9363 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364
9365 # clean memory
9366 delete($SymbolInfo{$LibVersion});
9367
9368 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 { # detect allocable classes with public exported constructors
9370 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009371 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009372 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009373 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009374 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009375 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9376 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009377 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009378 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009380 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009381 $AllocableClass{$LibVersion}{$ClassName} = 1;
9382 }
9383 }
9384 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009385 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009387 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009388 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009389 if($CheckHeadersOnly)
9390 {
9391 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9392 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9393 { # all symbols except non-virtual inline
9394 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9395 }
9396 }
9397 else {
9398 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 }
9400 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009401 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009402 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009403 }
9404 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009405 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009407 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009409 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009410 if(defined $Base{"Type"}
9411 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009413 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 if($Name=~/<([^<>\s]+)>/)
9415 {
9416 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9417 $ReturnedClass{$LibVersion}{$Tid} = 1;
9418 }
9419 }
9420 else {
9421 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9422 }
9423 }
9424 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009425 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009426 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009427 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009428 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009430 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009431 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009432 if($Base{"Type"}=~/Struct|Class/)
9433 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009434 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009435 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9436 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009437 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009439 }
9440 }
9441 }
9442 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009443
9444 # mapping {short name => symbols}
9445 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009447 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009448 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009449 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009451 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009453 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9454 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009455 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009456 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 }
9458 }
9459 }
9460 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009461
9462 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009463 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009464 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009467 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9468 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009469 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009470 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009471 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009472 $ClassNames{$LibVersion}{$TName} = 1;
9473 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009474 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009475 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9476 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009477 }
9478 }
9479 }
9480 }
9481 }
9482}
9483
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009484sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009485{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009486 my ($Tid, $LibVersion) = @_;
9487 if(not $Tid) {
9488 return $Tid;
9489 }
9490
9491 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9492 {
9493 if($TName_Tid{$LibVersion}{$Name}) {
9494 return $TName_Tid{$LibVersion}{$Name};
9495 }
9496 }
9497
9498 return $Tid;
9499}
9500
9501sub register_SymbolUsage($$$)
9502{
9503 my ($InfoId, $UsedType, $LibVersion) = @_;
9504
9505 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9506 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9507 {
9508 register_TypeUsage($RTid, $UsedType, $LibVersion);
9509 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9510 }
9511 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9512 {
9513 register_TypeUsage($FCid, $UsedType, $LibVersion);
9514 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9515
9516 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9517 { # register "this" pointer
9518 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9519 }
9520 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9521 { # register "this" pointer (const method)
9522 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9523 }
9524 }
9525 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9526 {
9527 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9528 {
9529 register_TypeUsage($PTid, $UsedType, $LibVersion);
9530 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9531 }
9532 }
9533 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9534 {
9535 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9536 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9537 register_TypeUsage($TTid, $UsedType, $LibVersion);
9538 }
9539 }
9540}
9541
9542sub register_TypeUsage($$$)
9543{
9544 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009545 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009546 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009547 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009549 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009550 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009551 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009552
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009553 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009554 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009556 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009557 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009558 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9559 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9560 }
9561 }
9562
9563 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9564 {
9565 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009566 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009567 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009568 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9569 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009570 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009571 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9572 {
9573 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9574 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009575 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009576 }
9577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009578 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009579 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009580 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009581 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9582 {
9583 register_TypeUsage($MTid, $UsedType, $LibVersion);
9584 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009585 }
9586 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009587 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009588 or $TInfo{"Type"} eq "MethodPtr"
9589 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009590 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009591 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009592 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009593 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009594 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009595 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009596 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9597 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009598 }
9599 }
9600 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009601 if($TInfo{"Type"} eq "FieldPtr")
9602 {
9603 if(my $RTid = $TInfo{"Return"}) {
9604 register_TypeUsage($RTid, $UsedType, $LibVersion);
9605 }
9606 if(my $CTid = $TInfo{"Class"}) {
9607 register_TypeUsage($CTid, $UsedType, $LibVersion);
9608 }
9609 }
9610 if($TInfo{"Type"} eq "MethodPtr")
9611 {
9612 if(my $CTid = $TInfo{"Class"}) {
9613 register_TypeUsage($CTid, $UsedType, $LibVersion);
9614 }
9615 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009616 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009617 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009618 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009619 $UsedType->{$TypeId} = 1;
9620 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9621 {
9622 register_TypeUsage($BTid, $UsedType, $LibVersion);
9623 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9624 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009625 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009626 else
9627 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9628 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009629 }
9630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009631}
9632
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009633sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009634{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9636
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009637 if($Level eq "Dump")
9638 {
9639 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9640 { # TODO: check if this symbol is from
9641 # base classes of other target symbols
9642 return 1;
9643 }
9644 }
9645
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009646 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9647 { # stdc++ interfaces
9648 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009649 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009650
9651 my $Target = 0;
9652 if(my $Header = $SInfo->{"Header"}) {
9653 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9654 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009655 if($ExtendedCheck)
9656 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009657 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009658 $Target = 1;
9659 }
9660 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009661 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009662 {
9663 if($Target)
9664 {
9665 if($Level eq "Dump")
9666 { # dumped
9667 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009668 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009669 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009670 return 1;
9671 }
9672 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009673 else {
9674 return 1;
9675 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009676 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009677 elsif($Level eq "Source")
9678 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009679 return 1;
9680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009681 elsif($Level eq "Binary")
9682 { # checked
9683 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9684 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9685 return 1;
9686 }
9687 }
9688 }
9689 }
9690 else
9691 { # library is available
9692 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9693 { # exported symbols
9694 return 1;
9695 }
9696 if($Level eq "Dump")
9697 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009698 if($BinaryOnly)
9699 {
9700 if($SInfo->{"Data"})
9701 {
9702 if($Target) {
9703 return 1;
9704 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009705 }
9706 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009707 else
9708 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009709 if($Target) {
9710 return 1;
9711 }
9712 }
9713 }
9714 elsif($Level eq "Source")
9715 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009716 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009717 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009718 { # skip LOCAL symbols
9719 if($Target) {
9720 return 1;
9721 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009722 }
9723 }
9724 elsif($Level eq "Binary")
9725 { # checked
9726 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9727 {
9728 if($Target) {
9729 return 1;
9730 }
9731 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009732 }
9733 }
9734 return 0;
9735}
9736
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009737sub cleanDump($)
9738{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009739 my $LibVersion = $_[0];
9740 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9741 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009742 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9743 {
9744 delete($SymbolInfo{$LibVersion}{$InfoId});
9745 next;
9746 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009747 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009748 if(not $MnglName)
9749 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009750 delete($SymbolInfo{$LibVersion}{$InfoId});
9751 next;
9752 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009753 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009754 if(not $ShortName)
9755 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009756 delete($SymbolInfo{$LibVersion}{$InfoId});
9757 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009758 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009759 if($MnglName eq $ShortName)
9760 { # remove duplicate data
9761 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009762 }
9763 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9764 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9765 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009766 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9767 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9768 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009769 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009770 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009771 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009772 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009773 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9774 {
9775 delete($TypeInfo{$LibVersion}{$Tid});
9776 next;
9777 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009778 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009779 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009780 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009781 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9782 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9783 }
9784 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009785 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9786 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9787 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009788 }
9789}
9790
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009791sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009792{
9793 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009794
9795 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9796 {
9797 if(defined $TypeInfo{$LibVersion}{$Dupl})
9798 {
9799 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9800 { # duplicate
9801 return 0;
9802 }
9803 }
9804 }
9805
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009806 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9807
9808 if(isBuiltIn($THeader)) {
9809 return 0;
9810 }
9811
9812 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9813 return 0;
9814 }
9815
9816 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9817 return 0;
9818 }
9819
9820 if(selfTypedef($Tid, $LibVersion)) {
9821 return 0;
9822 }
9823
9824 if(not isTargetType($Tid, $LibVersion)) {
9825 return 0;
9826 }
9827
9828 return 0;
9829}
9830
9831sub isTargetType($$)
9832{
9833 my ($Tid, $LibVersion) = @_;
9834
9835 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9836 { # derived
9837 return 1;
9838 }
9839
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009840 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009841 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009842 if(not is_target_header($THeader, $LibVersion))
9843 { # from target headers
9844 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009845 }
9846 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009847 else
9848 { # NOTE: if type is defined in source
9849 if($UsedDump{$LibVersion}{"Public"})
9850 {
9851 if(isPrivateABI($Tid, $LibVersion)) {
9852 return 0;
9853 }
9854 else {
9855 return 1;
9856 }
9857 }
9858 else {
9859 return 0;
9860 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009861 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009862
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009863 if($SkipInternalTypes)
9864 {
9865 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9866 {
9867 return 0;
9868 }
9869 }
9870
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009871 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009872}
9873
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009874sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009875{ # remove unused data types from the ABI dump
9876 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009877
9878 my %UsedType = ();
9879
9880 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009881 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009882 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009883 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009884 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009885 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009886 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009887 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009888 next;
9889 }
9890
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009891 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009892 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009893 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009894 {
9895 my %Tree = ();
9896 register_TypeUsage($Tid, \%Tree, $LibVersion);
9897
9898 my $Tmpl = 0;
9899 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9900 {
9901 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9902 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9903 {
9904 $Tmpl = 1;
9905 last;
9906 }
9907 }
9908 if(not $Tmpl)
9909 {
9910 foreach (keys(%Tree)) {
9911 $UsedType{$_} = 1;
9912 }
9913 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009914 }
9915 }
9916 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009917
9918 my %Delete = ();
9919
9920 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009921 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009922 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009923 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009924 next;
9925 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009926
9927 if($Kind eq "Extra")
9928 {
9929 my %Tree = ();
9930 register_TypeUsage($Tid, \%Tree, $LibVersion);
9931
9932 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9933 {
9934 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9935 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9936 {
9937 $Delete{$Tid} = 1;
9938 last;
9939 }
9940 }
9941 }
9942 else
9943 {
9944 # remove type
9945 delete($TypeInfo{$LibVersion}{$Tid});
9946 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009947 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009948
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009949 if($Kind eq "Extra")
9950 { # remove duplicates
9951 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9952 {
9953 if($UsedType{$Tid})
9954 { # All & Extended
9955 next;
9956 }
9957
9958 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9959
9960 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9961 delete($TypeInfo{$LibVersion}{$Tid});
9962 }
9963 }
9964 }
9965
9966 foreach my $Tid (keys(%Delete))
9967 {
9968 delete($TypeInfo{$LibVersion}{$Tid});
9969 }
9970}
9971
9972sub check_Completeness($$)
9973{
9974 my ($Info, $LibVersion) = @_;
9975
9976 # data types
9977 if(defined $Info->{"Memb"})
9978 {
9979 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9980 {
9981 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9982 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9983 }
9984 }
9985 }
9986 if(defined $Info->{"Base"})
9987 {
9988 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9989 check_TypeInfo($Bid, $LibVersion);
9990 }
9991 }
9992 if(defined $Info->{"BaseType"}) {
9993 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9994 }
9995 if(defined $Info->{"TParam"})
9996 {
9997 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9998 {
9999 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10000 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10001 next;
10002 }
10003 if($TName eq "_BoolType") {
10004 next;
10005 }
10006 if($TName=~/\Asizeof\(/) {
10007 next;
10008 }
10009 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10010 check_TypeInfo($Tid, $LibVersion);
10011 }
10012 else
10013 {
10014 if(defined $Debug) {
10015 printMsg("WARNING", "missed type $TName");
10016 }
10017 }
10018 }
10019 }
10020
10021 # symbols
10022 if(defined $Info->{"Param"})
10023 {
10024 foreach my $Pos (keys(%{$Info->{"Param"}}))
10025 {
10026 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10027 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10028 }
10029 }
10030 }
10031 if(defined $Info->{"Return"}) {
10032 check_TypeInfo($Info->{"Return"}, $LibVersion);
10033 }
10034 if(defined $Info->{"Class"}) {
10035 check_TypeInfo($Info->{"Class"}, $LibVersion);
10036 }
10037}
10038
10039sub check_TypeInfo($$)
10040{
10041 my ($Tid, $LibVersion) = @_;
10042
10043 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10044 return;
10045 }
10046 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10047
10048 if(defined $TypeInfo{$LibVersion}{$Tid})
10049 {
10050 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10051 printMsg("ERROR", "missed type name ($Tid)");
10052 }
10053 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10054 }
10055 else {
10056 printMsg("ERROR", "missed type id $Tid");
10057 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010058}
10059
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010060sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010061{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010062 my ($TypeId, $LibVersion) = @_;
10063 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010064 if($Type{"Type"} eq "Typedef")
10065 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010066 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010067 if($Base{"Type"}=~/Class|Struct/)
10068 {
10069 if($Type{"Name"} eq $Base{"Name"}) {
10070 return 1;
10071 }
10072 elsif($Type{"Name"}=~/::(\w+)\Z/)
10073 {
10074 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10075 { # QPointer<QWidget>::QPointer
10076 return 1;
10077 }
10078 }
10079 }
10080 }
10081 return 0;
10082}
10083
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010084sub addExtension($)
10085{
10086 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010087 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010088 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010089 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010090 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010091 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10092 $TName=~s/\A(struct|union|class|enum) //;
10093 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010094
10095 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10096 "Header" => "extended.h",
10097 "ShortName" => $Symbol,
10098 "MnglName" => $Symbol,
10099 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10100 );
10101
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010102 $ExtendedSymbols{$Symbol} = 1;
10103 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10104 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010105 }
10106 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010107 $ExtendedSymbols{"external_func_0"} = 1;
10108 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10109 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010110}
10111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010112sub findMethod($$$)
10113{
10114 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010115 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010116 {
10117 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10118 return $VirtMethodInClass;
10119 }
10120 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10121 return $VirtMethodInBaseClasses;
10122 }
10123 }
10124 return "";
10125}
10126
10127sub findMethod_Class($$$)
10128{
10129 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010130 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010131 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10132 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10133 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10134 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10135 { # search for interface with the same parameters suffix (overridden)
10136 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10137 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010138 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10139 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010140 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10141 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010142 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10143 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10144 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10145 return $Candidate;
10146 }
10147 }
10148 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010149 else
10150 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010151 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10152 return $Candidate;
10153 }
10154 }
10155 }
10156 }
10157 return "";
10158}
10159
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010160sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010161{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010162 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010163 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010164 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010165 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10166 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010167 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010168 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010169 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010170 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10171 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 { # pure virtual D2-destructors are marked as "virt" in the dump
10173 # virtual D2-destructors are NOT marked as "virt" in the dump
10174 # both destructors are not presented in the v-table
10175 next;
10176 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010177 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010178 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010180 }
10181}
10182
10183sub registerOverriding($)
10184{
10185 my $LibVersion = $_[0];
10186 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010187 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010188 foreach my $ClassName (@Classes)
10189 {
10190 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10191 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010192 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10193 { # pure virtuals
10194 next;
10195 }
10196 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10197 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010198 {
10199 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10200 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10201 { # both overridden virtual methods
10202 # and implemented pure virtual methods
10203 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10204 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10205 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 }
10208 }
10209 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10210 delete($VirtualTable{$LibVersion}{$ClassName});
10211 }
10212 }
10213}
10214
10215sub setVirtFuncPositions($)
10216{
10217 my $LibVersion = $_[0];
10218 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10219 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010220 my ($Num, $Rel) = (1, 0);
10221
10222 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010223 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010224 if($UsedDump{$LibVersion}{"DWARF"}) {
10225 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10226 }
10227 else {
10228 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10229 }
10230 foreach my $VirtFunc (@Funcs)
10231 {
10232 if($UsedDump{$LibVersion}{"DWARF"}) {
10233 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10234 }
10235 else {
10236 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10237 }
10238
10239 # set relative positions
10240 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10241 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10242 { # relative position excluding added and removed virtual functions
10243 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10244 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10245 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010249 }
10250 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010251 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 {
10253 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010254 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010255 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256 }
10257 }
10258}
10259
10260sub get_sub_classes($$$)
10261{
10262 my ($ClassId, $LibVersion, $Recursive) = @_;
10263 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10264 my @Subs = ();
10265 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10266 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010267 if($Recursive)
10268 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010269 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10270 push(@Subs, $SubSubId);
10271 }
10272 }
10273 push(@Subs, $SubId);
10274 }
10275 return @Subs;
10276}
10277
10278sub get_base_classes($$$)
10279{
10280 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010281 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010282 return () if(not defined $ClassType{"Base"});
10283 my @Bases = ();
10284 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10285 keys(%{$ClassType{"Base"}}))
10286 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010287 if($Recursive)
10288 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010289 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10290 push(@Bases, $SubBaseId);
10291 }
10292 }
10293 push(@Bases, $BaseId);
10294 }
10295 return @Bases;
10296}
10297
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010298sub getVTable_Model($$)
10299{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010300 my ($ClassId, $LibVersion) = @_;
10301 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10302 my @Elements = ();
10303 foreach my $BaseId (@Bases, $ClassId)
10304 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010305 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010306 {
10307 if(defined $VirtualTable{$LibVersion}{$BName})
10308 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010309 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10310 if($UsedDump{$LibVersion}{"DWARF"}) {
10311 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10312 }
10313 else {
10314 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10315 }
10316 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010317 push(@Elements, $VFunc);
10318 }
10319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010320 }
10321 }
10322 return @Elements;
10323}
10324
10325sub getVShift($$)
10326{
10327 my ($ClassId, $LibVersion) = @_;
10328 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10329 my $VShift = 0;
10330 foreach my $BaseId (@Bases)
10331 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010332 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010333 {
10334 if(defined $VirtualTable{$LibVersion}{$BName}) {
10335 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010337 }
10338 }
10339 return $VShift;
10340}
10341
10342sub getShift($$)
10343{
10344 my ($ClassId, $LibVersion) = @_;
10345 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10346 my $Shift = 0;
10347 foreach my $BaseId (@Bases)
10348 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010349 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010350 {
10351 if($Size!=1)
10352 { # not empty base class
10353 $Shift+=$Size;
10354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010355 }
10356 }
10357 return $Shift;
10358}
10359
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010360sub getVTable_Size($$)
10361{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010362 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010363 my $Size = 0;
10364 # three approaches
10365 if(not $Size)
10366 { # real size
10367 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10368 $Size = keys(%VTable);
10369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010370 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010371 if(not $Size)
10372 { # shared library symbol size
10373 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10374 $Size /= $WORD_SIZE{$LibVersion};
10375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010376 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010377 if(not $Size)
10378 { # model size
10379 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10380 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10381 }
10382 }
10383 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384}
10385
10386sub isCopyingClass($$)
10387{
10388 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010389 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010390}
10391
10392sub isLeafClass($$)
10393{
10394 my ($ClassId, $LibVersion) = @_;
10395 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10396}
10397
10398sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010399{ # check structured type for public fields
10400 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401}
10402
10403sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010404{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010405 my ($TypePtr, $Skip, $Start, $End) = @_;
10406 return 0 if(not $TypePtr);
10407 if($End==-1) {
10408 $End = keys(%{$TypePtr->{"Memb"}})-1;
10409 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010410 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010411 {
10412 if($Skip and $Skip->{$MemPos})
10413 { # skip removed/added fields
10414 next;
10415 }
10416 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10417 {
10418 if(isPublic($TypePtr, $MemPos)) {
10419 return ($MemPos+1);
10420 }
10421 }
10422 }
10423 return 0;
10424}
10425
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426sub isReserved($)
10427{ # reserved fields == private
10428 my $MName = $_[0];
10429 if($MName=~/reserved|padding|f_spare/i) {
10430 return 1;
10431 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010432 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010433 return 1;
10434 }
10435 if($MName=~/(pad\d+)/i) {
10436 return 1;
10437 }
10438 return 0;
10439}
10440
10441sub isPublic($$)
10442{
10443 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010445 return 0 if(not $TypePtr);
10446 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10447 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010448
10449 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10450 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010451 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010452 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010454
10455 # by name in C language
10456 # TODO: add other methods to detect private members
10457 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010458 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010459 { # C-styled private data
10460 return 0;
10461 }
10462 if(lc($MName) eq "abi")
10463 { # ABI information/reserved field
10464 return 0;
10465 }
10466 if(isReserved($MName))
10467 { # reserved fields
10468 return 0;
10469 }
10470
10471 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472}
10473
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010474sub getVTable_Real($$)
10475{
10476 my ($ClassName, $LibVersion) = @_;
10477 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10478 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010479 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010480 if(defined $Type{"VTable"}) {
10481 return %{$Type{"VTable"}};
10482 }
10483 }
10484 return ();
10485}
10486
10487sub cmpVTables($)
10488{
10489 my $ClassName = $_[0];
10490 my $Res = cmpVTables_Real($ClassName, 1);
10491 if($Res==-1) {
10492 $Res = cmpVTables_Model($ClassName);
10493 }
10494 return $Res;
10495}
10496
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497sub cmpVTables_Model($)
10498{
10499 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010500 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010501 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010503 return 1;
10504 }
10505 }
10506 return 0;
10507}
10508
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010509sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510{
10511 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010512 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10513 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010514 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010515 my %VTable_Old = getVTable_Real($ClassName, 1);
10516 my %VTable_New = getVTable_Real($ClassName, 2);
10517 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010519 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010521 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010522 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10523 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010524 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010525 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010527 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 my $Entry1 = $VTable_Old{$Offset};
10529 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010530 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010531 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010532 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010533 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010535 $Entry1 = simpleVEntry($Entry1);
10536 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010537
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010538 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010539 { # NOTE: problem with vtable-dumper
10540 next;
10541 }
10542
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010543 if($Entry1 ne $Entry2)
10544 { # register as changed
10545 if($Entry1=~/::([^:]+)\Z/)
10546 {
10547 my $M1 = $1;
10548 if($Entry2=~/::([^:]+)\Z/)
10549 {
10550 my $M2 = $1;
10551 if($M1 eq $M2)
10552 { # overridden
10553 next;
10554 }
10555 }
10556 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010557 if(differentDumps("G"))
10558 {
10559 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10560 {
10561 # GCC 4.6.1: -0x00000000000000010
10562 # GCC 4.7.0: -16
10563 next;
10564 }
10565 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 }
10568 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570}
10571
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010572sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010574 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10576 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010577 my $ClassId = $TName_Tid{1}{$ClassName};
10578 if(isPrivateABI($ClassId, 1)) {
10579 next;
10580 }
10581
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010582 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 { # already registered
10584 next;
10585 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010586 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010588 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 foreach my $Symbol (@Affected)
10590 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010591 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010592 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010593 "Target"=>$ClassName);
10594 }
10595 }
10596 }
10597}
10598
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010599sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010600{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010601 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010602 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010604 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010605 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010606
10607 if(isPrivateABI($ClassId, 1)) {
10608 next;
10609 }
10610
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010611 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010612 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010613 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010614 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010615 if($TName_Tid{1}{$ClassName}
10616 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010617 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010618 if(defined $CompleteSignature{1}{$Symbol}
10619 and $CompleteSignature{1}{$Symbol}{"Virt"})
10620 { # override some method in v.1
10621 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010622 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010623 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010624 }
10625 }
10626 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010627 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010630 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010631 if($TName_Tid{2}{$ClassName}
10632 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010633 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010634 if(defined $CompleteSignature{2}{$Symbol}
10635 and $CompleteSignature{2}{$Symbol}{"Virt"})
10636 { # override some method in v.2
10637 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010638 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010639 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010640 }
10641 }
10642 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010643 if($Level eq "Binary")
10644 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010645 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010646 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10647 { # check replacements, including pure virtual methods
10648 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10649 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010650 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010651 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10652 if($AddedPos==$RemovedPos)
10653 {
10654 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10655 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10656 last; # other methods will be reported as "added" or "removed"
10657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010658 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010659 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10660 {
10661 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10662 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 next;
10664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010665 my $ProblemType = "Virtual_Replacement";
10666 my @Affected = ($RemovedVFunc);
10667 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10668 { # pure methods
10669 if(not isUsedClass($ClassId, 1, $Level))
10670 { # not a parameter of some exported method
10671 next;
10672 }
10673 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010674
10675 # affected all methods (both virtual and non-virtual ones)
10676 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10677 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010678 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010679 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010680 foreach my $AffectedInt (@Affected)
10681 {
10682 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10683 { # affected exported methods only
10684 next;
10685 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010686 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10687 next;
10688 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010689 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10690 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010691 "Target"=>get_Signature($AddedVFunc, 2),
10692 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010694 }
10695 }
10696 }
10697 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010698 if(not checkDump(1, "2.0")
10699 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010700 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010701 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010702 return;
10703 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010704 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010705 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010706 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010707 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010708
10709 if(isPrivateABI($ClassId_Old, 1)) {
10710 next;
10711 }
10712
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010713 if(not isCreatable($ClassId_Old, 1))
10714 { # skip classes without public constructors (including auto-generated)
10715 # example: class has only a private exported or private inline constructor
10716 next;
10717 }
10718 if($ClassName=~/>/)
10719 { # skip affected template instances
10720 next;
10721 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010722 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010723 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010724 if(not $ClassId_New) {
10725 next;
10726 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010727 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010728 if($Class_New{"Type"}!~/Class|Struct/)
10729 { # became typedef
10730 if($Level eq "Binary") {
10731 next;
10732 }
10733 if($Level eq "Source")
10734 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010735 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010736 if($Class_New{"Type"}!~/Class|Struct/) {
10737 next;
10738 }
10739 $ClassId_New = $Class_New{"Tid"};
10740 }
10741 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010742
10743 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10744 { # incomplete info in the ABI dump
10745 next;
10746 }
10747
10748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010749 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10750 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 +040010751
10752 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10753 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10754
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010756 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10757 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010758 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10759 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 my $Shift_Old = getShift($ClassId_Old, 1);
10761 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010762 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010763 my ($Added, $Removed) = (0, 0);
10764 my @StableBases_Old = ();
10765 foreach my $BaseId (@Bases_Old)
10766 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010767 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010768 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 push(@StableBases_Old, $BaseId);
10770 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010771 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010772 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 { # removed base
10774 # excluding namespace::SomeClass to SomeClass renaming
10775 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010776 if($Level eq "Binary")
10777 { # Binary-level
10778 if($Shift_Old ne $Shift_New)
10779 { # affected fields
10780 if(havePubFields(\%Class_Old)) {
10781 $ProblemKind .= "_And_Shift";
10782 }
10783 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10784 $ProblemKind .= "_And_Size";
10785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010786 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010787 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10788 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010789 { # affected v-table
10790 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010791 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010792 }
10793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010794 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010795 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10796 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010797 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10798 {
10799 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10800 if($ProblemKind=~/VTable/) {
10801 $VTableChanged_M{$SubName}=1;
10802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 }
10804 }
10805 foreach my $Interface (@Affected)
10806 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010807 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10808 next;
10809 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010810 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010811 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010812 "Target"=>$BaseName,
10813 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10814 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10815 "Shift"=>abs($Shift_New-$Shift_Old) );
10816 }
10817 $Removed+=1;
10818 }
10819 }
10820 my @StableBases_New = ();
10821 foreach my $BaseId (@Bases_New)
10822 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010823 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010824 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010825 push(@StableBases_New, $BaseId);
10826 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010827 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010828 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 { # added base
10830 # excluding namespace::SomeClass to SomeClass renaming
10831 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010832 if($Level eq "Binary")
10833 { # Binary-level
10834 if($Shift_Old ne $Shift_New)
10835 { # affected fields
10836 if(havePubFields(\%Class_Old)) {
10837 $ProblemKind .= "_And_Shift";
10838 }
10839 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10840 $ProblemKind .= "_And_Size";
10841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010842 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010843 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10844 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010845 { # affected v-table
10846 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010847 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010848 }
10849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010851 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10852 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010853 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10854 {
10855 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10856 if($ProblemKind=~/VTable/) {
10857 $VTableChanged_M{$SubName}=1;
10858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 }
10860 }
10861 foreach my $Interface (@Affected)
10862 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010863 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10864 next;
10865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 "Target"=>$BaseName,
10869 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10870 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10871 "Shift"=>abs($Shift_New-$Shift_Old) );
10872 }
10873 $Added+=1;
10874 }
10875 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010876 if($Level eq "Binary")
10877 { # Binary-level
10878 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010879 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10880 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010882 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010883 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010884 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010885 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010886 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10887 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010888 if($NewPos!=$OldPos)
10889 { # changed position of the base class
10890 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010891 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010892 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10893 next;
10894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010895 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10896 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 "Target"=>$BaseName,
10898 "Old_Value"=>$OldPos-1,
10899 "New_Value"=>$NewPos-1 );
10900 }
10901 }
10902 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10903 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10904 { # became non-virtual base
10905 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10906 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010907 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10908 next;
10909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010910 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10911 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010912 "Target"=>$BaseName );
10913 }
10914 }
10915 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10916 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10917 { # became virtual base
10918 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10919 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010920 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10921 next;
10922 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010923 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10924 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010925 "Target"=>$BaseName );
10926 }
10927 }
10928 }
10929 }
10930 # detect size changes in base classes
10931 if($Shift_Old!=$Shift_New)
10932 { # size of allocable class
10933 foreach my $BaseId (@StableBases_Old)
10934 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010935 my %BaseType = get_Type($BaseId, 1);
10936 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010937 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010938 if($Size_Old ne $Size_New
10939 and $Size_Old and $Size_New)
10940 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010941 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010942 if(isCopyingClass($BaseId, 1)) {
10943 $ProblemType = "Size_Of_Copying_Class";
10944 }
10945 elsif($AllocableClass{1}{$BaseType{"Name"}})
10946 {
10947 if($Size_New>$Size_Old)
10948 { # increased size
10949 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010950 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010951 else
10952 { # decreased size
10953 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10954 if(not havePubFields(\%Class_Old))
10955 { # affected class has no public members
10956 next;
10957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010959 }
10960 next if(not $ProblemType);
10961 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10962 { # base class size changes affecting current class
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}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10967 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010968 "Target"=>$BaseType{"Name"},
10969 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10970 "New_Size"=>$Size_New*$BYTE_SIZE );
10971 }
10972 }
10973 }
10974 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010975 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010976 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010977 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010978 { # compare virtual tables size in base classes
10979 my $VShift_Old = getVShift($ClassId_Old, 1);
10980 my $VShift_New = getVShift($ClassId_New, 2);
10981 if($VShift_Old ne $VShift_New)
10982 { # changes in the base class or changes in the list of base classes
10983 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10984 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10985 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010986 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 foreach my $BaseId (@AllBases_Old)
10988 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010989 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010990 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010991 { # lost base
10992 next;
10993 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010994 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10995 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 if($VSize_Old!=$VSize_New)
10997 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010998 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010999 { # TODO: affected non-virtual methods?
11000 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011001 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11002 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011003 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011004 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011005 { # skip interfaces that have not changed the absolute virtual position
11006 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011007 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011008 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11009 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011010 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011011 $VTableChanged_M{$BaseType{"Name"}} = 1;
11012 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011013 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11014 { # the reason of the layout change: added virtual functions
11015 next if($VirtualReplacement{$VirtFunc});
11016 my $ProblemType = "Added_Virtual_Method";
11017 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11018 $ProblemType = "Added_Pure_Virtual_Method";
11019 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011020 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011021 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 "Target"=>get_Signature($VirtFunc, 2) );
11023 }
11024 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11025 { # the reason of the layout change: removed virtual functions
11026 next if($VirtualReplacement{$VirtFunc});
11027 my $ProblemType = "Removed_Virtual_Method";
11028 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11029 $ProblemType = "Removed_Pure_Virtual_Method";
11030 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011031 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 "Target"=>get_Signature($VirtFunc, 1) );
11034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011035 }
11036 }
11037 }
11038 }
11039 }
11040 }
11041 }
11042}
11043
11044sub isCreatable($$)
11045{
11046 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011047 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011048 or isCopyingClass($ClassId, $LibVersion)) {
11049 return 1;
11050 }
11051 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11052 { # Fix for incomplete data: if this class has
11053 # a base class then it should also has a constructor
11054 return 1;
11055 }
11056 if($ReturnedClass{$LibVersion}{$ClassId})
11057 { # returned by some method of this class
11058 # or any other class
11059 return 1;
11060 }
11061 return 0;
11062}
11063
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011064sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011065{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011066 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11068 { # parameter of some exported method
11069 return 1;
11070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011071 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11072 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011073 { # method from target class
11074 return 1;
11075 }
11076 return 0;
11077}
11078
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011079sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011080{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011081 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011082 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011083 # - virtual
11084 # - pure-virtual
11085 # - non-virtual
11086 if($CompleteSignature{1}{$Interface}{"Data"})
11087 { # global data is not affected
11088 return;
11089 }
11090 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011091 if(not $Class_Id) {
11092 return;
11093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011094 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011095 if(cmpVTables_Real($CName, 1)==0)
11096 { # no changes
11097 return;
11098 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 $CheckedTypes{$Level}{$CName} = 1;
11100 if($Level eq "Binary")
11101 { # Binary-level
11102 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11103 and not isUsedClass($Class_Id, 1, $Level))
11104 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011105 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011107 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011108 }
11109 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11110 {
11111 if(defined $VirtualTable{2}{$CName}{$Func}
11112 and defined $CompleteSignature{2}{$Func})
11113 {
11114 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11115 and $CompleteSignature{2}{$Func}{"PureVirt"})
11116 { # became pure virtual
11117 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11118 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011119 "Target"=>get_Signature_M($Func, 1) );
11120 $VTableChanged_M{$CName} = 1;
11121 }
11122 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11123 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11124 { # became non-pure virtual
11125 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11126 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011127 "Target"=>get_Signature_M($Func, 1) );
11128 $VTableChanged_M{$CName} = 1;
11129 }
11130 }
11131 }
11132 if($Level eq "Binary")
11133 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011134 # check virtual table structure
11135 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11136 {
11137 next if($Interface eq $AddedVFunc);
11138 next if($VirtualReplacement{$AddedVFunc});
11139 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11140 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11141 { # pure virtual methods affect all others (virtual and non-virtual)
11142 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011145 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011146 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011147 elsif(not defined $VirtualTable{1}{$CName}
11148 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011149 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011150 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 { # became polymorphous class, added v-table pointer
11152 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011153 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011154 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011156 }
11157 else
11158 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011159 my $VSize_Old = getVTable_Size($CName, 1);
11160 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011161 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011162 if(isCopyingClass($Class_Id, 1))
11163 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11164 my $ProblemType = "Added_Virtual_Method";
11165 if(isLeafClass($Class_Id, 1)) {
11166 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11167 }
11168 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11169 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011171 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 else
11174 {
11175 my $ProblemType = "Added_Virtual_Method";
11176 if(isLeafClass($Class_Id, 1)) {
11177 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11178 }
11179 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11180 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011181 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011182 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011184 }
11185 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011186 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11187 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011188 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011189 if(defined $VirtualTable{1}{$CName}
11190 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011191 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011192 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11193 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011194
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011195 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011196 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011197 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11198 foreach my $ASymbol (@Affected)
11199 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011200 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11201 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011202 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011203 next;
11204 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011205 }
11206 $CheckedSymbols{$Level}{$ASymbol} = 1;
11207 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11208 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011209 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011210 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011213 }
11214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011215 else {
11216 # safe
11217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011219 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11220 {
11221 next if($VirtualReplacement{$RemovedVFunc});
11222 if($RemovedVFunc eq $Interface
11223 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11224 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011225 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 next;
11227 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011228 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011229 { # became non-polymorphous class, removed v-table pointer
11230 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11231 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011232 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011233 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 }
11235 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11236 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11237 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011238 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011239 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011240 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11241 next;
11242 }
11243 my $VPos_New = -1;
11244 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011246 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11247 }
11248 else
11249 {
11250 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011251 next;
11252 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 }
11254 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11255 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11256 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11257 {
11258 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11259 foreach my $ASymbol (@Affected)
11260 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011261 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11262 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011263 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011264 next;
11265 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011266 }
11267 my $ProblemType = "Removed_Virtual_Method";
11268 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11269 $ProblemType = "Removed_Pure_Virtual_Method";
11270 }
11271 $CheckedSymbols{$Level}{$ASymbol} = 1;
11272 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11273 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011274 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011275 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011276 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011277 }
11278 }
11279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011280 }
11281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011282 else
11283 { # Source-level
11284 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011285 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011286 next if($Interface eq $AddedVFunc);
11287 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011288 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011289 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11290 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011291 "Target"=>get_Signature($AddedVFunc, 2) );
11292 }
11293 }
11294 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11295 {
11296 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11297 {
11298 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11299 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011300 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011301 }
11302 }
11303 }
11304}
11305
11306sub find_MemberPair_Pos_byName($$)
11307{
11308 my ($Member_Name, $Pair_Type) = @_;
11309 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11310 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11311 {
11312 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11313 {
11314 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11315 $Name=~s/\A[_]+|[_]+\Z//g;
11316 if($Name eq $Member_Name) {
11317 return $MemberPair_Pos;
11318 }
11319 }
11320 }
11321 return "lost";
11322}
11323
11324sub find_MemberPair_Pos_byVal($$)
11325{
11326 my ($Member_Value, $Pair_Type) = @_;
11327 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11328 {
11329 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11330 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11331 return $MemberPair_Pos;
11332 }
11333 }
11334 return "lost";
11335}
11336
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011337sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011338{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011339 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011340 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011341 if( $_->{"T1"} eq $_[0]
11342 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011343 {
11344 return 1;
11345 }
11346 }
11347 return 0;
11348}
11349
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011350sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011351{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011352 my %IDs = (
11353 "T1" => $_[0],
11354 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011355 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011356 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357}
11358
11359sub isRenamed($$$$$)
11360{
11361 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11362 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11363 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011364 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 if(not defined $Type2->{"Memb"}{$MemPos}) {
11366 return "";
11367 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011368 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011369 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011370
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011371 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11372 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011373 if($MemberPair_Pos_Rev eq "lost")
11374 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011375 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11376 { # base type match
11377 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011379 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11380 { # exact type match
11381 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011382 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011383 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11384 { # size match
11385 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011387 if(isReserved($Pair_Name))
11388 { # reserved fields
11389 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011390 }
11391 }
11392 return "";
11393}
11394
11395sub isLastElem($$)
11396{
11397 my ($Pos, $TypeRef) = @_;
11398 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011399 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011400 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11401 return 1;
11402 }
11403 elsif($Name=~/END|NLIMITS\Z/)
11404 { # __RLIMIT_NLIMITS
11405 return 1;
11406 }
11407 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11408 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11409 { # NImageFormats, NColorRoles
11410 return 1;
11411 }
11412 return 0;
11413}
11414
11415sub nonComparable($$)
11416{
11417 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011418
11419 my $N1 = $T1->{"Name"};
11420 my $N2 = $T2->{"Name"};
11421
11422 $N1=~s/\A(struct|union|enum) //;
11423 $N2=~s/\A(struct|union|enum) //;
11424
11425 if($N1 ne $N2
11426 and not isAnon($N1)
11427 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011428 { # different names
11429 if($T1->{"Type"} ne "Pointer"
11430 or $T2->{"Type"} ne "Pointer")
11431 { # compare base types
11432 return 1;
11433 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011434 if($N1!~/\Avoid\s*\*/
11435 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011436 {
11437 return 1;
11438 }
11439 }
11440 elsif($T1->{"Type"} ne $T2->{"Type"})
11441 { # different types
11442 if($T1->{"Type"} eq "Class"
11443 and $T2->{"Type"} eq "Struct")
11444 { # "class" to "struct"
11445 return 0;
11446 }
11447 elsif($T2->{"Type"} eq "Class"
11448 and $T1->{"Type"} eq "Struct")
11449 { # "struct" to "class"
11450 return 0;
11451 }
11452 else
11453 { # "class" to "enum"
11454 # "union" to "class"
11455 # ...
11456 return 1;
11457 }
11458 }
11459 return 0;
11460}
11461
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011462sub isOpaque($)
11463{
11464 my $T = $_[0];
11465 if(not defined $T->{"Memb"})
11466 {
11467 return 1;
11468 }
11469 return 0;
11470}
11471
11472sub removeVPtr($)
11473{ # support for old ABI dumps
11474 my $TPtr = $_[0];
11475 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11476 if($#Pos>=1)
11477 {
11478 foreach my $Pos (0 .. $#Pos-1)
11479 {
11480 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11481 }
11482 delete($TPtr->{"Memb"}{$#Pos});
11483 }
11484}
11485
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011486sub isPrivateABI($$)
11487{
11488 my ($TypeId, $LibVersion) = @_;
11489
11490 if($CheckPrivateABI) {
11491 return 0;
11492 }
11493
11494 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11495 return 1;
11496 }
11497
11498 return 0;
11499}
11500
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011501sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011502{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011503 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011504 return {} if(not $Type1_Id or not $Type2_Id);
11505
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011506 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011507 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011508 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011509 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011510
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011511 my %Type1 = get_Type($Type1_Id, 1);
11512 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011513 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011514 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011515 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011516
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011517 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11518 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011519
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011520 if(defined $UsedDump{1}{"DWARF"})
11521 {
11522 if($Type1_Pure{"Name"} eq "__unknown__"
11523 or $Type2_Pure{"Name"} eq "__unknown__")
11524 { # Error ABI dump
11525 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11526 }
11527 }
11528
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011529 if(isPrivateABI($Type1_Id, 1)) {
11530 return {};
11531 }
11532
11533 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11534 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11535
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011536 my %SubProblems = ();
11537
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011538 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11539 {
11540 if($Type1_Pure{"Type"}=~/Struct|Union/
11541 and $Type2_Pure{"Type"}=~/Struct|Union/)
11542 {
11543 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11544 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011545 if(not defined $UsedDump{1}{"DWARF"}
11546 and not defined $UsedDump{2}{"DWARF"})
11547 {
11548 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11549 "Target"=>$Type1_Pure{"Name"},
11550 "Type_Name"=>$Type1_Pure{"Name"} );
11551 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011552
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011553 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011554 }
11555 }
11556 }
11557
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011558 if(not $Type1_Pure{"Size"}
11559 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011560 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011561 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11562 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11563 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011564 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011565 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011566 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011567 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011568 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011569 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011570 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011571 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11572 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11573 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011574
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011575 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11576 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011577 }
11578
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011579 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11580 { # support for old ABI dumps
11581 # _vptr field added in 3.0
11582 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11583 {
11584 if(defined $Type2_Pure{"Memb"}
11585 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11586 {
11587 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11588 delete($Type2_Pure{"Memb"}{0});
11589 }
11590 else {
11591 removeVPtr(\%Type2_Pure);
11592 }
11593 }
11594 }
11595 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11596 {
11597 if(defined $Type1_Pure{"Memb"}
11598 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11599 {
11600 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11601 delete($Type1_Pure{"Memb"}{0});
11602 }
11603 else {
11604 removeVPtr(\%Type1_Pure);
11605 }
11606 }
11607 }
11608 }
11609
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011610 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11611 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011612
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011613 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011614 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11615 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011616 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011617 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11618 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011619 if($Base_1{"Name"} ne $Base_2{"Name"})
11620 {
11621 if(differentDumps("G")
11622 or differentDumps("V"))
11623 { # different GCC versions or different dumps
11624 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11625 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11626 # std::__va_list and __va_list
11627 $Base_1{"Name"}=~s/\A(\w+::)+//;
11628 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011629 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11630 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011632 }
11633 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11634 and $Base_1{"Name"} ne $Base_2{"Name"})
11635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011636 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011637 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011638 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011639 {
11640 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11641 "Target"=>$Typedef_1{"Name"},
11642 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011643 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11644 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11645 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011646 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11647 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011648
11649 if(defined $UsedDump{1}{"DWARF"})
11650 {
11651 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11652 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11653 { # Error ABI dump
11654 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11655 }
11656 }
11657
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011658 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011659 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011660 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11661 {
11662 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11663 "Target"=>$Typedef_1{"Name"},
11664 "Type_Name"=>$Typedef_1{"Name"},
11665 "Old_Value"=>$Base_1{"Name"},
11666 "New_Value"=>$Base_2{"Name"} );
11667 }
11668 else
11669 {
11670 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11671 "Target"=>$Typedef_1{"Name"},
11672 "Type_Name"=>$Typedef_1{"Name"},
11673 "Old_Value"=>$Base_1{"Name"},
11674 "New_Value"=>$Base_2{"Name"} );
11675 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011677 }
11678 }
11679 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11680 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011681 my $TT1 = $Type1_Pure{"Type"};
11682 my $TT2 = $Type2_Pure{"Type"};
11683
11684 if($TT1 ne $TT2
11685 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011687 my $Short1 = $Type1_Pure{"Name"};
11688 my $Short2 = $Type2_Pure{"Name"};
11689
11690 $Short1=~s/\A\Q$TT1\E //ig;
11691 $Short2=~s/\A\Q$TT2\E //ig;
11692
11693 if($Short1 eq $Short2)
11694 {
11695 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11696 "Target"=>$Type1_Pure{"Name"},
11697 "Type_Name"=>$Type1_Pure{"Name"},
11698 "Old_Value"=>lc($Type1_Pure{"Type"}),
11699 "New_Value"=>lc($Type2_Pure{"Type"}) );
11700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011701 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011702 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011703 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011704
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011705 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011706
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011707 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11708 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11709 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11710 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011711 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011712 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011713 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011714 {
11715 my $ProblemKind = "DataType_Size";
11716 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011717 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011718 {
11719 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11720 $ProblemKind = "Size_Of_Copying_Class";
11721 }
11722 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11723 {
11724 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11725 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11726 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011727 else
11728 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 # descreased size of allocable class
11730 # it has no special effects
11731 }
11732 }
11733 }
11734 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11735 "Target"=>$Type1_Pure{"Name"},
11736 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011737 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011738 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011739 }
11740 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011741 if(defined $Type1_Pure{"BaseType"}
11742 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011743 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011744 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11745 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011746 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011747 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11748 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011749 }
11750 }
11751 }
11752 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11753 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11754 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11755 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11756 { # detect removed and renamed fields
11757 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11758 next if(not $Member_Name);
11759 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);
11760 if($MemberPair_Pos eq "lost")
11761 {
11762 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11763 {
11764 if(isUnnamed($Member_Name))
11765 { # support for old-version dumps
11766 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011767 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011768 next;
11769 }
11770 }
11771 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11772 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011773 $RenamedField{$Member_Pos} = $RenamedTo;
11774 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011775 }
11776 else
11777 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011778 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 }
11780 }
11781 elsif($Type1_Pure{"Type"} eq "Enum")
11782 {
11783 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11784 next if($Member_Value1 eq "");
11785 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11786 if($MemberPair_Pos ne "lost")
11787 { # renamed
11788 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11789 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11790 if($MemberPair_Pos_Rev eq "lost")
11791 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011792 $RenamedField{$Member_Pos} = $RenamedTo;
11793 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 }
11795 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011796 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011797 }
11798 }
11799 else
11800 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011801 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 }
11803 }
11804 }
11805 else
11806 { # related
11807 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11808 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11809 }
11810 }
11811 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11812 { # detect added fields
11813 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11814 next if(not $Member_Name);
11815 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);
11816 if($MemberPair_Pos eq "lost")
11817 {
11818 if(isUnnamed($Member_Name))
11819 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011820 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011821 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011822 next;
11823 }
11824 }
11825 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11826 {
11827 if(not $RenamedField_Rev{$Member_Pos})
11828 { # added
11829 $AddedField{$Member_Pos}=1;
11830 }
11831 }
11832 }
11833 }
11834 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11835 { # detect moved fields
11836 my (%RelPos, %RelPosName, %AbsPos) = ();
11837 my $Pos = 0;
11838 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11839 { # relative positions in 1st version
11840 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11841 next if(not $Member_Name);
11842 if(not $RemovedField{$Member_Pos})
11843 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011844 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011845 $RelPosName{1}{$Pos} = $Member_Name;
11846 $AbsPos{1}{$Pos++} = $Member_Pos;
11847 }
11848 }
11849 $Pos = 0;
11850 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11851 { # relative positions in 2nd version
11852 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11853 next if(not $Member_Name);
11854 if(not $AddedField{$Member_Pos})
11855 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011856 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011857 $RelPosName{2}{$Pos} = $Member_Name;
11858 $AbsPos{2}{$Pos++} = $Member_Pos;
11859 }
11860 }
11861 foreach my $Member_Name (keys(%{$RelPos{1}}))
11862 {
11863 my $RPos1 = $RelPos{1}{$Member_Name};
11864 my $AbsPos1 = $NameToPosA{$Member_Name};
11865 my $Member_Name2 = $Member_Name;
11866 if(my $RenamedTo = $RenamedField{$AbsPos1})
11867 { # renamed
11868 $Member_Name2 = $RenamedTo;
11869 }
11870 my $RPos2 = $RelPos{2}{$Member_Name2};
11871 if($RPos2 ne "" and $RPos1 ne $RPos2)
11872 { # different relative positions
11873 my $AbsPos2 = $NameToPosB{$Member_Name2};
11874 if($AbsPos1 ne $AbsPos2)
11875 { # different absolute positions
11876 my $ProblemType = "Moved_Field";
11877 if(not isPublic(\%Type1_Pure, $AbsPos1))
11878 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011879 if($Level eq "Source") {
11880 next;
11881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011882 $ProblemType = "Moved_Private_Field";
11883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011884 if($Level eq "Binary"
11885 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011886 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011887 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011888 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011889 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011890 if($MemSize1 ne $MemSize2) {
11891 $ProblemType .= "_And_Size";
11892 }
11893 }
11894 if($ProblemType eq "Moved_Private_Field") {
11895 next;
11896 }
11897 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11898 "Target"=>$Member_Name,
11899 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011900 "Old_Value"=>$RPos1,
11901 "New_Value"=>$RPos2 );
11902 }
11903 }
11904 }
11905 }
11906 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011907 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011908 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11909 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011910 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011911 if(my $RenamedTo = $RenamedField{$Member_Pos})
11912 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011913 if(defined $Constants{2}{$Member_Name})
11914 {
11915 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11916 { # define OLD NEW
11917 next; # Safe
11918 }
11919 }
11920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011921 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11922 {
11923 if(isPublic(\%Type1_Pure, $Member_Pos))
11924 {
11925 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11926 "Target"=>$Member_Name,
11927 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011928 "Old_Value"=>$Member_Name,
11929 "New_Value"=>$RenamedTo );
11930 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011931 elsif(isReserved($Member_Name))
11932 {
11933 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11934 "Target"=>$Member_Name,
11935 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011936 "Old_Value"=>$Member_Name,
11937 "New_Value"=>$RenamedTo );
11938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011939 }
11940 elsif($Type1_Pure{"Type"} eq "Enum")
11941 {
11942 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11943 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11944 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 "Old_Value"=>$Member_Name,
11946 "New_Value"=>$RenamedTo );
11947 }
11948 }
11949 elsif($RemovedField{$Member_Pos})
11950 { # removed
11951 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11952 {
11953 my $ProblemType = "Removed_Field";
11954 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011955 or isUnnamed($Member_Name))
11956 {
11957 if($Level eq "Source") {
11958 next;
11959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011960 $ProblemType = "Removed_Private_Field";
11961 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011962 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011963 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011964 {
11965 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11966 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011967 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 +040011968 { # changed offset
11969 $ProblemType .= "_And_Layout";
11970 }
11971 }
11972 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11973 { # affected size
11974 $ProblemType .= "_And_Size";
11975 }
11976 }
11977 if($ProblemType eq "Removed_Private_Field") {
11978 next;
11979 }
11980 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11981 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011982 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 }
11984 elsif($Type2_Pure{"Type"} eq "Union")
11985 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011986 if($Level eq "Binary"
11987 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011988 {
11989 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11990 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011991 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011992 }
11993 else
11994 {
11995 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11996 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011997 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011998 }
11999 }
12000 elsif($Type1_Pure{"Type"} eq "Enum")
12001 {
12002 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12003 "Target"=>$Member_Name,
12004 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012005 "Old_Value"=>$Member_Name );
12006 }
12007 }
12008 else
12009 { # changed
12010 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12011 if($Type1_Pure{"Type"} eq "Enum")
12012 {
12013 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12014 next if($Member_Value1 eq "");
12015 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12016 next if($Member_Value2 eq "");
12017 if($Member_Value1 ne $Member_Value2)
12018 {
12019 my $ProblemType = "Enum_Member_Value";
12020 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12021 $ProblemType = "Enum_Last_Member_Value";
12022 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012023 if($SkipConstants{1}{$Member_Name}) {
12024 $ProblemType = "Enum_Private_Member_Value";
12025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012026 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12027 "Target"=>$Member_Name,
12028 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012029 "Old_Value"=>$Member_Value1,
12030 "New_Value"=>$Member_Value2 );
12031 }
12032 }
12033 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12034 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012035 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12036 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12037
12038 if($Access1 ne "private"
12039 and $Access2 eq "private")
12040 {
12041 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12042 "Target"=>$Member_Name,
12043 "Type_Name"=>$Type1_Pure{"Name"});
12044 }
12045 elsif($Access1 ne "protected"
12046 and $Access1 ne "private"
12047 and $Access2 eq "protected")
12048 {
12049 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12050 "Target"=>$Member_Name,
12051 "Type_Name"=>$Type1_Pure{"Name"});
12052 }
12053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012054 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12055 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012056 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12058 $SizeV1 = $BSize1;
12059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012060 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012061 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12062 $SizeV2 = $BSize2;
12063 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012064 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12065 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012066 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012067 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012068 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012069 {
12070 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12071 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12072 { # field size change (including anon-structures and unions)
12073 # - same types
12074 # - unnamed types
12075 # - bitfields
12076 my $ProblemType = "Field_Size";
12077 if(not isPublic(\%Type1_Pure, $Member_Pos)
12078 or isUnnamed($Member_Name))
12079 { # should not be accessed by applications, goes to "Low Severity"
12080 # example: "abidata" members in GStreamer types
12081 $ProblemType = "Private_".$ProblemType;
12082 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012083 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 +040012084 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012085 if($Type2_Pure{"Type"} ne "Union"
12086 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012088 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 +040012089 { # changed offset
12090 $ProblemType .= "_And_Layout";
12091 }
12092 }
12093 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12094 $ProblemType .= "_And_Type_Size";
12095 }
12096 }
12097 if($ProblemType eq "Private_Field_Size")
12098 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012099 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012100 if($ProblemType eq "Field_Size")
12101 {
12102 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12103 { # Low severity
12104 $ProblemType = "Struct_Field_Size_Increased";
12105 }
12106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012107 if($ProblemType)
12108 { # register a problem
12109 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12110 "Target"=>$Member_Name,
12111 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012112 "Old_Size"=>$SizeV1,
12113 "New_Size"=>$SizeV2);
12114 }
12115 }
12116 }
12117 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12118 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12119 { # do NOT check bitfield type changes
12120 next;
12121 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012122 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012123 {
12124 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12125 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12126 {
12127 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12128 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012129 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012130 }
12131 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12132 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12133 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012134 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012135 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012136 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012137 }
12138 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012139 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12140 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012141 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012142 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12143 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012144
12145 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012146 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012147 or $ProblemType eq "Field_Type_And_Size"
12148 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012150 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012151 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012152 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012153 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012155 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012156 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012157 }
12158 }
12159 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12160 {
12161 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012162 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012163 }
12164 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012165 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012166 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012167 }
12168 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12169 {
12170 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012171 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012172 }
12173 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012174 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012175 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012176 }
12177 }
12178 }
12179
12180 if($Level eq "Source")
12181 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012182 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012183 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012184 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12185 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012186
12187 if($ProblemType eq "Field_Type")
12188 {
12189 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012190 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012191 }
12192 }
12193 }
12194 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012195
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012196 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 {
12198 my $ProblemType_Init = $ProblemType;
12199 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012200 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012201 if(not isPublic(\%Type1_Pure, $Member_Pos)
12202 or isUnnamed($Member_Name)) {
12203 $ProblemType = "Private_".$ProblemType;
12204 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012205 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 +040012206 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012207 if($Type2_Pure{"Type"} ne "Union"
12208 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012209 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012210 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 +040012211 { # changed offset
12212 $ProblemType .= "_And_Layout";
12213 }
12214 }
12215 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12216 $ProblemType .= "_And_Type_Size";
12217 }
12218 }
12219 }
12220 else
12221 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012222 # TODO: Private_Field_Type rule?
12223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012224 if(not isPublic(\%Type1_Pure, $Member_Pos)
12225 or isUnnamed($Member_Name)) {
12226 next;
12227 }
12228 }
12229 if($ProblemType eq "Private_Field_Type_And_Size")
12230 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012231 }
12232 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12233 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012234 "Type_Name"=>$Type1_Pure{"Name"});
12235
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012236 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012237 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012238 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012239 }
12240 }
12241 if(not isPublic(\%Type1_Pure, $Member_Pos))
12242 { # do NOT check internal type changes
12243 next;
12244 }
12245 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012246 { # checking member type changes
12247 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12248
12249 my %DupProblems = ();
12250
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012251 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012253 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012254 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012255 if(not defined $AllAffected)
12256 {
12257 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12258 next;
12259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012261
12262 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12263 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12264
12265 if(not defined $AllAffected)
12266 {
12267 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 }
12269 }
12270 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012271
12272 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012273 }
12274 }
12275 }
12276 }
12277 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12278 { # checking added members, public and private
12279 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12280 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012281 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012282 if($AddedField{$Member_Pos})
12283 { # added
12284 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12285 {
12286 my $ProblemType = "Added_Field";
12287 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012288 or isUnnamed($Member_Name))
12289 {
12290 if($Level eq "Source") {
12291 next;
12292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 $ProblemType = "Added_Private_Field";
12294 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012295 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012296 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012297 {
12298 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12299 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012300 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 +040012301 { # changed offset
12302 $ProblemType .= "_And_Layout";
12303 }
12304 }
12305 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12306 $ProblemType .= "_And_Size";
12307 }
12308 }
12309 if($ProblemType eq "Added_Private_Field")
12310 { # skip added private fields
12311 next;
12312 }
12313 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12314 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012315 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012316 }
12317 elsif($Type2_Pure{"Type"} eq "Union")
12318 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012319 if($Level eq "Binary"
12320 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012321 {
12322 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12323 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012324 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325 }
12326 else
12327 {
12328 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12329 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012330 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012331 }
12332 }
12333 elsif($Type2_Pure{"Type"} eq "Enum")
12334 {
12335 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12336 next if($Member_Value eq "");
12337 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12338 "Target"=>$Member_Name,
12339 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012340 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012341 }
12342 }
12343 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012344
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012345 if($Type1_Pure{"Type"} eq "FuncPtr")
12346 {
12347 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12348 {
12349 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12350 next;
12351 }
12352
12353 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12354 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12355
12356 my $PName = "p".$PPos;
12357
12358 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12359 my %DupProblems = ();
12360
12361 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12362 {
12363 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12364 {
12365 if(not defined $AllAffected)
12366 {
12367 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12368 next;
12369 }
12370 }
12371
12372 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12373 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12374
12375 if(not defined $AllAffected)
12376 {
12377 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12378 }
12379 }
12380 }
12381
12382 %DupProblems = ();
12383 }
12384 }
12385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012387 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388}
12389
12390sub isUnnamed($) {
12391 return $_[0]=~/\Aunnamed\d+\Z/;
12392}
12393
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012394sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012395{
12396 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012397 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12398 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12399 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12400 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012401 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012402 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012403 }
12404 return $TypeName;
12405}
12406
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012407sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012408{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012409 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012410 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012411 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12412 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012413 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012414 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12415 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012416 return () if(not $Type{"Type"});
12417 if($Type{"Type"} ne $Type_Type)
12418 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012419 return () if(not $Type{"BaseType"});
12420 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012421 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012422 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 return %Type;
12424}
12425
12426my %TypeSpecAttributes = (
12427 "Const" => 1,
12428 "Volatile" => 1,
12429 "ConstVolatile" => 1,
12430 "Restrict" => 1,
12431 "Typedef" => 1
12432);
12433
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012434sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012436 my ($TypeId, $Info) = @_;
12437 if(not $TypeId or not $Info
12438 or not $Info->{$TypeId}) {
12439 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012441 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12442 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12443 }
12444 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012445 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012447 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012448 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012449 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012450 return %Type;
12451}
12452
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012453sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012455 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012457 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12458 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012459 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012460 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12461 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012462 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12463 my $PLevel = 0;
12464 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12465 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012467 return $PLevel if(not $Type{"BaseType"});
12468 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12469 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12470 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012471}
12472
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012473sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012477 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12478 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012479 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012480 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12481 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012482 return %Type if(not $Type{"BaseType"});
12483 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012484 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012485 return %Type;
12486}
12487
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012488sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012489{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012490 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012491 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012492 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12493 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012494 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012495 my $Qual = "";
12496 if($Type{"Type"} eq "Pointer") {
12497 $Qual .= "*";
12498 }
12499 elsif($Type{"Type"} eq "Ref") {
12500 $Qual .= "&";
12501 }
12502 elsif($Type{"Type"} eq "ConstVolatile") {
12503 $Qual .= "const volatile";
12504 }
12505 elsif($Type{"Type"} eq "Const"
12506 or $Type{"Type"} eq "Volatile"
12507 or $Type{"Type"} eq "Restrict") {
12508 $Qual .= lc($Type{"Type"});
12509 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012510 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 return $BQual.$Qual;
12512}
12513
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012514sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012516 my ($TypeId, $Info) = @_;
12517 if(not $TypeId or not $Info
12518 or not $Info->{$TypeId}) {
12519 return ();
12520 }
12521 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012522 return %Type if(not $Type{"BaseType"});
12523 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012524 {
12525 if($Info->{$BTid}) {
12526 return %{$Info->{$BTid}};
12527 }
12528 else { # something is going wrong
12529 return ();
12530 }
12531 }
12532 else {
12533 return %Type;
12534 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012535}
12536
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012537sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012538{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012539 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012540 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012541 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12542 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543}
12544
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012545sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012546{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012547 my $Symbol = $_[0];
12548 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12549}
12550
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012551sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012552 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12553}
12554
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012555sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012557 my ($SInfo, $LibVersion) = @_;
12558
12559 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012560 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012561 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012562 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012563 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012564 return 1;
12565 }
12566 }
12567 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012568 if(my $ShortName = $SInfo->{"ShortName"})
12569 {
12570 if(index($ShortName,"<")!=-1
12571 and index($ShortName,">")!=-1) {
12572 return 1;
12573 }
12574 }
12575
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012576 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012577}
12578
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012579sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012581 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012582 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012583 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012584 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585 { # class specialization
12586 return 1;
12587 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012588 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 { # method specialization
12590 return 1;
12591 }
12592 }
12593 return 0;
12594}
12595
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012596sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012598 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012599
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012600 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012601 { # non-public global data
12602 return 0;
12603 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012604
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012605 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012606 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012607 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012608 }
12609
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012610 if($Symbol=~/\A_Z/)
12611 {
12612 if($Symbol=~/[CD][3-4]E/) {
12613 return 0;
12614 }
12615 }
12616
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012617 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 { # support for old ABI dumps in --headers-only mode
12619 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12620 {
12621 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12622 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012623 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 if(not $PType or $PType eq "Unknown") {
12625 return 0;
12626 }
12627 }
12628 }
12629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012630 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012632 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012634 if($SkipSymbols{$LibVersion}{$Symbol})
12635 { # user defined symbols to ignore
12636 return 0;
12637 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012638
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012639 if($SymbolsListPath and not $SymbolsList{$Symbol})
12640 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012641 if(not $TargetHeadersPath or not $Header
12642 or not is_target_header($Header, 1))
12643 { # -symbols-list | -headers-list
12644 return 0;
12645 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012646 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012647
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012648 if($AppPath and not $SymbolsList_App{$Symbol})
12649 { # user defined symbols (in application)
12650 return 0;
12651 }
12652
12653 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12654
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012655 if($ClassId)
12656 {
12657 if(not isTargetType($ClassId, $LibVersion)) {
12658 return 0;
12659 }
12660 }
12661
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12663 if(not $NameSpace and $ClassId)
12664 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012665 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 }
12667 if($NameSpace)
12668 { # user defined namespaces to ignore
12669 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12670 return 0;
12671 }
12672 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12673 { # nested namespaces
12674 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12675 return 0;
12676 }
12677 }
12678 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012679 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012681 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012682 { # --skip-headers or <skip_headers> (not <skip_including>)
12683 if($Skip==1) {
12684 return 0;
12685 }
12686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012687 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012688 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012689 { # user defined types
12690 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12691
12692 if(not $TypesList{$CName})
12693 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012694 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12695 {
12696 $CName=~s/\A\Q$NS\E\:\://g;
12697 }
12698
12699 if(not $TypesList{$CName})
12700 {
12701 my $Found = 0;
12702
12703 while($CName=~s/\:\:.+?\Z//)
12704 {
12705 if($TypesList{$CName})
12706 {
12707 $Found = 1;
12708 last;
12709 }
12710 }
12711
12712 if(not $Found) {
12713 return 0;
12714 }
12715 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012716 }
12717 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012718
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012719 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12720 { # non-target symbols
12721 return 0;
12722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012723 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012724 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012725 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12726 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012727 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012728 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12729 { # inline virtual methods
12730 if($Type=~/InlineVirt/) {
12731 return 1;
12732 }
12733 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12734 if(not $Allocable)
12735 { # check bases
12736 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12737 {
12738 if(not isCopyingClass($DCId, $LibVersion))
12739 { # exists a derived class without default c-tor
12740 $Allocable=1;
12741 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012743 }
12744 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012745 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012746 return 0;
12747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012748 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012749 else
12750 { # inline non-virtual methods
12751 return 0;
12752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754 }
12755 }
12756 return 1;
12757}
12758
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012759sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012760{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012761 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012762 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12763 {
12764 if(link_symbol($Symbol, 1, "+Deps"))
12765 { # linker can find a new symbol
12766 # in the old-version library
12767 # So, it's not a new symbol
12768 next;
12769 }
12770 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012771 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012772 next;
12773 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775 }
12776}
12777
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012778sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012780 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012781 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12782 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012783 if(link_symbol($Symbol, 2, "+Deps"))
12784 { # linker can find an old symbol
12785 # in the new-version library
12786 next;
12787 }
12788 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012789 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012790 next;
12791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012792 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012793 }
12794}
12795
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012796sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012798 my $Level = $_[0];
12799 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012800 { # checking added symbols
12801 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012802 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012803 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012804 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012805 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012806 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012807 { # checking removed symbols
12808 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012809 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012810 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012811 { # skip v-tables for templates, that should not be imported by applications
12812 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012813 if(my $CName = $VTableClass{$Symbol})
12814 {
12815 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12816 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012817 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012818 next;
12819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012820 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012821
12822 if($SkipSymbols{1}{$Symbol})
12823 { # user defined symbols to ignore
12824 next;
12825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012826 }
12827 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012828 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012829 }
12830 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12831 { # symbols for pure virtual methods cannot be called by clients
12832 next;
12833 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012834 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012835 }
12836}
12837
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012838sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012839{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012840 my ($LibVersion, $V) = @_;
12841 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12842 return $Cache{"checkDump"}{$LibVersion}{$V};
12843 }
12844 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012845}
12846
12847sub detectAdded_H($)
12848{
12849 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012850 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12851 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012852 if($Level eq "Source")
12853 { # remove symbol version
12854 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12855 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012856
12857 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12858 { # skip artificial constructors
12859 next;
12860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012862 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12863 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012864 next;
12865 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012866 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012867 next;
12868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 if(not defined $CompleteSignature{1}{$Symbol}
12870 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12871 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012872 if($UsedDump{2}{"SrcBin"})
12873 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012874 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012875 { # support for old and different (!) ABI dumps
12876 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12877 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012878 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012879 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012880 {
12881 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12882 {
12883 if($Lang eq "C")
12884 { # support for old ABI dumps: missed extern "C" functions
12885 next;
12886 }
12887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012888 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012889 else
12890 {
12891 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012892 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012893 next;
12894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012895 }
12896 }
12897 }
12898 }
12899 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012900 }
12901 }
12902}
12903
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012904sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012905{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012906 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012907 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12908 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012909 if($Level eq "Source")
12910 { # remove symbol version
12911 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12912 $Symbol=$SN;
12913 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12915 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 next;
12917 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012918 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012919 next;
12920 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012921 if(not defined $CompleteSignature{2}{$Symbol}
12922 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012923 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012924 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012925 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012926 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012927 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012928 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12929 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012930 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012931 if($CheckHeadersOnly)
12932 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012933 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12934 {
12935 if($Lang eq "C")
12936 { # support for old ABI dumps: missed extern "C" functions
12937 next;
12938 }
12939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012940 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012941 else
12942 {
12943 if(not link_symbol($Symbol, 1, "-Deps"))
12944 { # skip removed inline symbols
12945 next;
12946 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012947 }
12948 }
12949 }
12950 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012951 if(not checkDump(1, "2.15"))
12952 {
12953 if($Symbol=~/_IT_E\Z/)
12954 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12955 next;
12956 }
12957 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012958 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12959 {
12960 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12961 {
12962 if(defined $Constants{2}{$Short})
12963 {
12964 my $Val = $Constants{2}{$Short}{"Value"};
12965 if(defined $Func_ShortName{2}{$Val})
12966 { # old name defined to new
12967 next;
12968 }
12969 }
12970 }
12971
12972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012973 $RemovedInt{$Level}{$Symbol} = 1;
12974 if($Level eq "Source")
12975 { # search for a source-compatible equivalent
12976 setAlternative($Symbol, $Level);
12977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012978 }
12979 }
12980}
12981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012983{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 my $Level = $_[0];
12985 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012986 { # checking added symbols
12987 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012988 next if($CompleteSignature{2}{$Symbol}{"Private"});
12989 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012990 if($Level eq "Binary")
12991 {
12992 if($CompleteSignature{2}{$Symbol}{"InLine"})
12993 {
12994 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12995 { # skip inline non-virtual functions
12996 next;
12997 }
12998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012999 }
13000 else
13001 { # Source
13002 if($SourceAlternative_B{$Symbol}) {
13003 next;
13004 }
13005 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013006 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013007 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013008 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013009 { # checking removed symbols
13010 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013011 next if($CompleteSignature{1}{$Symbol}{"Private"});
13012 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013013 if($Level eq "Binary")
13014 {
13015 if($CompleteSignature{1}{$Symbol}{"InLine"})
13016 {
13017 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13018 { # skip inline non-virtual functions
13019 next;
13020 }
13021 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013022 }
13023 else
13024 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013025 if(my $Alt = $SourceAlternative{$Symbol})
13026 {
13027 if(defined $CompleteSignature{1}{$Alt}
13028 and $CompleteSignature{1}{$Symbol}{"Const"})
13029 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013030 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013031 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013032 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013033 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013034 }
13035 else
13036 { # do NOT show removed symbol
13037 next;
13038 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013039 }
13040 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013041 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013042 }
13043}
13044
13045sub addParamNames($)
13046{
13047 my $LibraryVersion = $_[0];
13048 return if(not keys(%AddIntParams));
13049 my $SecondVersion = $LibraryVersion==1?2:1;
13050 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13051 {
13052 next if(not keys(%{$AddIntParams{$Interface}}));
13053 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013054 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013055 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13056 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013057 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013058 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13059 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13060 {
13061 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13062 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13063 }
13064 }
13065 else {
13066 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13067 }
13068 }
13069 }
13070 }
13071}
13072
13073sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013074{ # detect changed typedefs to show
13075 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013076 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13077 {
13078 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013079 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13080 if(not $BName1 or isAnon($BName1)) {
13081 next;
13082 }
13083 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13084 if(not $BName2 or isAnon($BName2)) {
13085 next;
13086 }
13087 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013088 $ChangedTypedef{$Typedef} = 1;
13089 }
13090 }
13091}
13092
13093sub get_symbol_suffix($$)
13094{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013095 my ($Symbol, $Full) = @_;
13096 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013097 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013098 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013099 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013100 if(not $Full) {
13101 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13102 }
13103 return $Suffix;
13104}
13105
13106sub get_symbol_prefix($$)
13107{
13108 my ($Symbol, $LibVersion) = @_;
13109 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13110 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13111 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013112 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 }
13114 return $ShortName;
13115}
13116
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013117sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013118{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013119 my $Symbol = $_[0];
13120 my $PSymbol = $Symbol;
13121 if(not defined $CompleteSignature{2}{$PSymbol}
13122 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13123 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13124 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013125 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013126 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013127 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013128 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013129 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13130 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013131 {
13132 if(defined $CompleteSignature{2}{$PSymbol}
13133 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13134 {
13135 $SourceAlternative{$Symbol} = $PSymbol;
13136 $SourceAlternative_B{$PSymbol} = $Symbol;
13137 if(not defined $CompleteSignature{1}{$PSymbol}
13138 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13139 $SourceReplacement{$Symbol} = $PSymbol;
13140 }
13141 }
13142 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013143 }
13144 else
13145 {
13146 foreach my $Sp ("KV", "VK", "K", "V")
13147 {
13148 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13149 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13150 {
13151 if(defined $CompleteSignature{2}{$PSymbol}
13152 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13153 {
13154 $SourceAlternative{$Symbol} = $PSymbol;
13155 $SourceAlternative_B{$PSymbol} = $Symbol;
13156 if(not defined $CompleteSignature{1}{$PSymbol}
13157 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13158 $SourceReplacement{$Symbol} = $PSymbol;
13159 }
13160 }
13161 }
13162 $PSymbol = $Symbol;
13163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013164 }
13165 }
13166 }
13167 return "";
13168}
13169
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013170sub getSymKind($$)
13171{
13172 my ($Symbol, $LibVersion) = @_;
13173 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13174 {
13175 return "Global_Data";
13176 }
13177 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13178 {
13179 return "Method";
13180 }
13181 return "Function";
13182}
13183
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013184sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013185{
13186 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013188
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 mergeBases($Level);
13190
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013193 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013194 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013195 next;
13196 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013197 if(defined $CompleteSignature{1}{$Symbol}
13198 and $CompleteSignature{1}{$Symbol}{"Header"})
13199 { # double-check added symbol
13200 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013202 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013203 next;
13204 }
13205 if($Symbol=~/\A(_Z|\?)/)
13206 { # C++
13207 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13208 }
13209 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13210 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013211 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13212 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013213 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013214 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013215 {
13216 if($TName_Tid{1}{$AffectedClass_Name})
13217 { # class should exist in previous version
13218 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13219 { # old v-table is NOT copied by old applications
13220 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13221 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013222 "Target"=>get_Signature($Symbol, 2),
13223 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013224 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013227 }
13228 }
13229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013230 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13231 { # check all removed exported symbols
13232 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013233 next;
13234 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013235 if(defined $CompleteSignature{2}{$Symbol}
13236 and $CompleteSignature{2}{$Symbol}{"Header"})
13237 { # double-check removed symbol
13238 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013239 }
13240 if($CompleteSignature{1}{$Symbol}{"Private"})
13241 { # skip private methods
13242 next;
13243 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013244 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013245 next;
13246 }
13247 $CheckedSymbols{$Level}{$Symbol} = 1;
13248 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13249 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013250 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13251 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013253 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13254 {
13255 if($TName_Tid{2}{$AffectedClass_Name})
13256 { # class should exist in newer version
13257 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13258 { # old v-table is NOT copied by old applications
13259 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13260 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013261 "Target"=>get_Signature($OverriddenMethod, 1),
13262 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013263 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 }
13267 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013268 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013269 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013271 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013273 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013274 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013275 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013276 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013277 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013278 {
13279 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13280 "Target"=>$tr_name{$Symbol},
13281 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013282 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013284 else
13285 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013286 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013287 "Target"=>$tr_name{$Symbol},
13288 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013289 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013290 }
13291 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013292 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013293 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013294 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013295 {
13296 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13297 "Target"=>$tr_name{$Symbol},
13298 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013299 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013301 else
13302 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013303 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 "Target"=>$tr_name{$Symbol},
13305 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013306 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 }
13308 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013309 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13310 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13311 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13312 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13313 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013314 {
13315 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013316 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013317 $ProblemType = "Global_Data_Symbol_Changed_Type";
13318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13320 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013321 "Old_Type"=>$RTName1,
13322 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013323 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013324 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325 }
13326 }
13327 }
13328 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013331 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013332 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013333 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013334 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013335 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013336 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13337 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013338 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013339 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013341 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 }
13343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013344 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13345 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013346 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013347 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013348 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013349 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 }
13351 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013352 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013354 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013359 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013362 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013364 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013369 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013371 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013377 { # "volatile" to non-"volatile"
13378
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013379 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013380 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013381 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013383 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013384 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013386 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013388 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013390 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013392 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013394 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013396 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13397 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013398 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013400 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 }
13402 }
13403 }
13404 }
13405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13407 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013408 $CurrentSymbol = $Symbol;
13409
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13411 if($Level eq "Source")
13412 { # remove symbol version
13413 $Symbol=$SN;
13414 }
13415 else
13416 { # Binary
13417 if(not $SV)
13418 { # symbol without version
13419 if(my $VSym = $SymVer{1}{$Symbol})
13420 { # the symbol is linked with versioned symbol
13421 if($CompleteSignature{2}{$VSym}{"MnglName"})
13422 { # show report for symbol@ver only
13423 next;
13424 }
13425 elsif(not link_symbol($VSym, 2, "-Deps"))
13426 { # changed version: sym@v1 to sym@v2
13427 # do NOT show report for symbol
13428 next;
13429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 }
13431 }
13432 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 my $PSymbol = $Symbol;
13434 if($Level eq "Source"
13435 and my $S = $SourceReplacement{$Symbol})
13436 { # take a source-compatible replacement function
13437 $PSymbol = $S;
13438 }
13439 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 { # private symbols
13441 next;
13442 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 if(not defined $CompleteSignature{1}{$Symbol}
13444 or not defined $CompleteSignature{2}{$PSymbol})
13445 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013446 next;
13447 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013448 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13449 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13450 { # no mangled name
13451 next;
13452 }
13453 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13454 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 { # without a header
13456 next;
13457 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013458
13459 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13460 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13461 { # became pure
13462 next;
13463 }
13464 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13465 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13466 { # became non-pure
13467 next;
13468 }
13469
13470 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13471 { # exported, target, inline virtual and pure virtual
13472 next;
13473 }
13474 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13475 { # exported, target, inline virtual and pure virtual
13476 next;
13477 }
13478
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013479 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013480 {
13481 if($CompleteSignature{1}{$Symbol}{"Data"}
13482 and $CompleteSignature{2}{$PSymbol}{"Data"})
13483 {
13484 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13485 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13486 if(defined $Value1)
13487 {
13488 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13489 if(defined $Value2)
13490 {
13491 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13492 if($Value1 ne $Value2)
13493 {
13494 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13495 "Old_Value"=>$Value1,
13496 "New_Value"=>$Value2,
13497 "Target"=>get_Signature($Symbol, 1) );
13498 }
13499 }
13500 }
13501 }
13502 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013503
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013504 if($CompleteSignature{2}{$PSymbol}{"Private"})
13505 {
13506 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13507 "Target"=>get_Signature_M($PSymbol, 2) );
13508 }
13509 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13510 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13511 {
13512 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13513 "Target"=>get_Signature_M($PSymbol, 2) );
13514 }
13515 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13516 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13517 {
13518 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13519 "Target"=>get_Signature_M($PSymbol, 2) );
13520 }
13521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013523 mergeVirtualTables($Symbol, $Level);
13524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013525 if($COMPILE_ERRORS)
13526 { # if some errors occurred at the compiling stage
13527 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013528 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013529 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 { # missed information about parameters in newer version
13531 next;
13532 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013533 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013534 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013535 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013536 next;
13537 }
13538 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013539 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013540 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013541 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013542 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13543 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013544 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13545 "Target"=>get_Signature($Symbol, 1)
13546 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013548 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013549 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13550 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013551 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013552 "Target"=>get_Signature($Symbol, 1)
13553 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013554 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013555 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13556 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013557 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013558 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013559 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013560 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13561 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13562 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013564 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013565 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13566 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013567 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013568 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013569 my $ProblemType = "Virtual_Method_Position";
13570 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13571 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013572 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 if(isUsedClass($Class_Id, 1, $Level))
13574 {
13575 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013576 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013578 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13579 next;
13580 }
13581 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013582 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13584 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013585 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013586 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013587 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 }
13590 }
13591 }
13592 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013593 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13594 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 { # do NOT check type changes in pure virtuals
13596 next;
13597 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013598 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013599 if($Symbol=~/\A(_Z|\?)/
13600 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013603 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013604 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 }
13606 }
13607 else
13608 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013609 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013610 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013611 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013612 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13613 last if($PType2_Name eq "...");
13614 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13615 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013617 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013619 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13620 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13622 $ParamPos_Prev = "lost";
13623 }
13624 }
13625 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013626 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 }
13628 if($ParamPos_Prev eq "lost")
13629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013631 {
13632 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013633 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013634 $ProblemType = "Added_Unnamed_Parameter";
13635 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013636 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013637 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013638 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013640 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013641 }
13642 else
13643 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013644 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013645 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013646 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013647 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13648 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013649 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013650 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013651 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013652 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013653 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013654 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013655 "Param_Type"=>$PType2_Name,
13656 "Old_Value"=>$PName_Old,
13657 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013658 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013659 }
13660 }
13661 else
13662 {
13663 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013664 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013665 $ProblemType = "Added_Middle_Unnamed_Parameter";
13666 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013667 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013668 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013669 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013670 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013671 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013672 }
13673 }
13674 }
13675 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013676 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013677 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013678 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013679 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013680 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013681 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013683 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013684 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013685 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13686 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013687 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 }
13689 }
13690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013691 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013692 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013693 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13695 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013696 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13697 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013698 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013699 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013701 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13702 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13704 $ParamPos_New = "lost";
13705 }
13706 }
13707 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013708 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 }
13710 if($ParamPos_New eq "lost")
13711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013712 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013713 {
13714 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013715 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 $ProblemType = "Removed_Unnamed_Parameter";
13717 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013718 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013719 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013720 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013722 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013723 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013724 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013725 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013726 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013727 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013728 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013729 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013730 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013732 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013733 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013734 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013735 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013736 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013737 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013738 "Old_Value"=>$PName,
13739 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013740 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 }
13742 }
13743 else
13744 {
13745 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013746 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013747 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13748 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013749 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013750 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013751 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013752 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013753 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013754 }
13755 }
13756 }
13757 }
13758 }
13759 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013760 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13761 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013762 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013763
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013764 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013765 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013766 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13767 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013768 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013769
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013770 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013772 if($SubProblemType eq "Return_Type_And_Size") {
13773 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13774 }
13775 elsif($SubProblemType eq "Return_Type_Format") {
13776 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13777 }
13778 else {
13779 $ProblemTypes{"Global_Data_Type"} = 1;
13780 }
13781
13782 # quals
13783 if($SubProblemType eq "Return_Type"
13784 or $SubProblemType eq "Return_Type_And_Size"
13785 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013786 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013787 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13788 { # const to non-const
13789 if($RR==2) {
13790 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13791 }
13792 else {
13793 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13794 }
13795 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013796 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013797 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13798 { # non-const to const
13799 if($RA==2) {
13800 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13801 }
13802 else {
13803 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13804 }
13805 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013806 }
13807 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013808 }
13809 else
13810 {
13811 # quals
13812 if($SubProblemType eq "Return_Type"
13813 or $SubProblemType eq "Return_Type_And_Size"
13814 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013815 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013816 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013817 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013818 if(addedQual($Old_Value, $New_Value, "volatile"))
13819 {
13820 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13821 if($Level ne "Source"
13822 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13823 $ProblemTypes{"Return_Type"} = 1;
13824 }
13825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013826 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013827 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13828 {
13829 if($RA==2) {
13830 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13831 }
13832 else {
13833 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13834 }
13835 if($Level ne "Source"
13836 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13837 $ProblemTypes{"Return_Type"} = 1;
13838 }
13839 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013840 }
13841 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013842 if($Level eq "Binary"
13843 and not $CompleteSignature{1}{$Symbol}{"Data"})
13844 {
13845 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13846 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13847 { # if one of the architectures is unknown
13848 # then set other arhitecture to unknown too
13849 ($Arch1, $Arch2) = ("unknown", "unknown");
13850 }
13851 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013853 {
13854 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13855 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13856 }
13857 else
13858 {
13859 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13860 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13861 }
13862
13863 if($SubProblemType eq "Return_Type_Became_Void")
13864 {
13865 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13866 { # parameters stack has been affected
13867 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013868 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013869 }
13870 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013871 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013872 }
13873 }
13874 }
13875 elsif($SubProblemType eq "Return_Type_From_Void")
13876 {
13877 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13878 { # parameters stack has been affected
13879 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013880 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013881 }
13882 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013883 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013884 }
13885 }
13886 }
13887 elsif($SubProblemType eq "Return_Type"
13888 or $SubProblemType eq "Return_Type_And_Size"
13889 or $SubProblemType eq "Return_Type_Format")
13890 {
13891 if($Conv1{"Method"} ne $Conv2{"Method"})
13892 {
13893 if($Conv1{"Method"} eq "stack")
13894 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013895 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013896 }
13897 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013899 }
13900 }
13901 else
13902 {
13903 if($Conv1{"Method"} eq "reg")
13904 {
13905 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13906 {
13907 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013908 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013909 }
13910 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013911 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013912 }
13913 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013914 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013915 }
13916 }
13917 }
13918 }
13919 }
13920 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013921
13922 if(not keys(%ProblemTypes))
13923 { # default
13924 $ProblemTypes{$SubProblemType} = 1;
13925 }
13926
13927 foreach my $ProblemType (keys(%ProblemTypes))
13928 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013929 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013931 }
13932 if($ReturnType1_Id and $ReturnType2_Id)
13933 {
13934 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013935 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13936
13937 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013938
13939 if($CompleteSignature{1}{$Symbol}{"Data"})
13940 {
13941 if($Level eq "Binary")
13942 {
13943 if(get_PLevel($ReturnType1_Id, 1)==0)
13944 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013945 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013947
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013948 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13949 {
13950 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013951 {
13952 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13953 {
13954 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13955 last;
13956 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013957 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013958 }
13959 }
13960 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013961 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013962 {
13963 if(defined $GlobalDataObject{1}{$Symbol}
13964 and defined $GlobalDataObject{2}{$Symbol})
13965 {
13966 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13967 my $New_Size = $GlobalDataObject{2}{$Symbol};
13968 if($Old_Size!=$New_Size)
13969 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013970 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013971 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013972 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013973 }
13974 }
13975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013976 }
13977 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013978
13979 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013980 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013981 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013982 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013983 my $NewLocation = "retval";
13984 if($SubLocation and $SubLocation ne "retval") {
13985 $NewLocation = "retval->".$SubLocation;
13986 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013987 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13988 }
13989 }
13990
13991 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13992 {
13993 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13994 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013995 my $NewLocation = "retval";
13996 if($SubLocation and $SubLocation ne "retval") {
13997 $NewLocation = "retval->".$SubLocation;
13998 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013999 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014000 }
14001 }
14002 }
14003
14004 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014005 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14006 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14007 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014008 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014009 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014010 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14011 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014012 if($ThisPtr1_Id and $ThisPtr2_Id)
14013 {
14014 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014015 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14016 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014017 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014018 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014019 {
14020 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014021 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014022 }
14023 }
14024 }
14025 }
14026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014027 if($Level eq "Binary") {
14028 mergeVTables($Level);
14029 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014030 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14031 $CheckedSymbols{$Level}{$Symbol} = 1;
14032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014033}
14034
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014035sub rmQuals($$)
14036{
14037 my ($Value, $Qual) = @_;
14038 if(not $Qual) {
14039 return $Value;
14040 }
14041 if($Qual eq "all")
14042 { # all quals
14043 $Qual = "const|volatile|restrict";
14044 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014045 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014046 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014047 }
14048 return $Value;
14049}
14050
14051sub cmpBTypes($$$$)
14052{
14053 my ($T1, $T2, $V1, $V2) = @_;
14054 $T1 = uncover_typedefs($T1, $V1);
14055 $T2 = uncover_typedefs($T2, $V2);
14056 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14057}
14058
14059sub addedQual($$$)
14060{
14061 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014062 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014063}
14064
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014065sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014066{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014067 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014068 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014069}
14070
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014071sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014072{
14073 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14074 $Old_Value = uncover_typedefs($Old_Value, $V1);
14075 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014076
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014077 if($Old_Value eq $New_Value)
14078 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014079 return 0;
14080 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014081 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014082 { # without a qual
14083 return 0;
14084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014085 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014086 { # became non-qual
14087 return 1;
14088 }
14089 else
14090 {
14091 my @BQ1 = getQualModel($Old_Value, $Qual);
14092 my @BQ2 = getQualModel($New_Value, $Qual);
14093 foreach (0 .. $#BQ1)
14094 { # removed qual
14095 if($BQ1[$_]==1
14096 and $BQ2[$_]!=1)
14097 {
14098 return 2;
14099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014100 }
14101 }
14102 return 0;
14103}
14104
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014105sub getQualModel($$)
14106{
14107 my ($Value, $Qual) = @_;
14108 if(not $Qual) {
14109 return $Value;
14110 }
14111
14112 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014113 while($Value=~/(\w+)/)
14114 {
14115 my $W = $1;
14116
14117 if($W eq $Qual) {
14118 $Value=~s/\b$W\b/\@/g;
14119 }
14120 else {
14121 $Value=~s/\b$W\b//g;
14122 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014123 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014124
14125 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014126 $Value=~s/[^\*\&\w]+//g;
14127
14128 # modeling
14129 # int*const*const == 011
14130 # int**const == 001
14131 my @Model = ();
14132 my @Elems = split(/[\*\&]/, $Value);
14133 if(not @Elems) {
14134 return (0);
14135 }
14136 foreach (@Elems)
14137 {
14138 if($_ eq $Qual) {
14139 push(@Model, 1);
14140 }
14141 else {
14142 push(@Model, 0);
14143 }
14144 }
14145
14146 return @Model;
14147}
14148
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014149my %StringTypes = map {$_=>1} (
14150 "char*",
14151 "char const*"
14152);
14153
14154my %CharTypes = map {$_=>1} (
14155 "char",
14156 "char const"
14157);
14158
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014159sub showVal($$$)
14160{
14161 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014162 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014163 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014164 if(substr($Value, 0, 2) eq "_Z")
14165 {
14166 if(my $Unmangled = $tr_name{$Value}) {
14167 return $Unmangled;
14168 }
14169 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014170 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014171 { # strings
14172 return "\"$Value\"";
14173 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014174 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014175 { # characters
14176 return "\'$Value\'";
14177 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014178 if($Value eq "")
14179 { # other
14180 return "\'\'";
14181 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182 return $Value;
14183}
14184
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014185sub getRegs($$$)
14186{
14187 my ($LibVersion, $Symbol, $Pos) = @_;
14188
14189 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14190 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014191 my %Regs = ();
14192 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14193 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014194 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014195 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14196 }
14197 }
14198
14199 return join(", ", sort keys(%Regs));
14200 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014201 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14202 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14203 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14204 {
14205 return "unknown";
14206 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014207
14208 return undef;
14209}
14210
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014211sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014212{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014213 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014214 if(not $Symbol) {
14215 return;
14216 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014217 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14218 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14219 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14220 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014221 if(not $PType1_Id
14222 or not $PType2_Id) {
14223 return;
14224 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014225
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014226 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014227 { # do not merge "this"
14228 if($PName1 eq "this" or $PName2 eq "this") {
14229 return;
14230 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014231 }
14232
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014233 my %Type1 = get_Type($PType1_Id, 1);
14234 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014235
14236 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14237
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014238 my %BaseType1 = get_BaseType($PType1_Id, 1);
14239 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014240
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014241 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014242
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014243 if($Level eq "Binary")
14244 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014245 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014246 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14247 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14248 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14249 {
14250 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014251 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014252 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014253 }
14254 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14255 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14256 {
14257 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014258 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014259 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014262
14263 if(defined $UsedDump{1}{"DWARF"}
14264 and defined $UsedDump{2}{"DWARF"})
14265 {
14266 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14267 {
14268 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14269 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014270
14271 if($Old_Regs ne "unknown"
14272 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014273 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014274 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014275 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014276 if($Old_Regs ne $New_Regs)
14277 {
14278 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14279 "Target"=>$PName1,
14280 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14281 "Old_Value"=>$Old_Regs,
14282 "New_Value"=>$New_Regs );
14283 }
14284 }
14285 elsif($Old_Regs and not $New_Regs)
14286 {
14287 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014288 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014289 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014290 "Old_Value"=>$Old_Regs );
14291 }
14292 elsif(not $Old_Regs and $New_Regs)
14293 {
14294 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14295 "Target"=>$PName1,
14296 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014297 "New_Value"=>$New_Regs );
14298 }
14299 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014300
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014301 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14302 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14303 {
14304 if($Old_Offset ne $New_Offset)
14305 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014306 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14307 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14308
14309 $Old_Offset = $Old_Offset - $Start1;
14310 $New_Offset = $New_Offset - $Start2;
14311
14312 if($Old_Offset ne $New_Offset)
14313 {
14314 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14315 "Target"=>$PName1,
14316 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14317 "Old_Value"=>$Old_Offset,
14318 "New_Value"=>$New_Offset );
14319 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014320 }
14321 }
14322 }
14323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014324 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014325 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14326 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014327 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014328 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014329 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14330 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014331 if(not checkDump(1, "2.13")
14332 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014333 { # support for old ABI dumps
14334 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014335 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014336 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014337 and $Value_Old eq "false" and $Value_New eq "0")
14338 { # int class::method ( bool p = 0 );
14339 # old ABI dumps: "false"
14340 # new ABI dumps: "0"
14341 $Value_Old = "0";
14342 }
14343 }
14344 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014345 if(not checkDump(1, "2.18")
14346 and checkDump(2, "2.18"))
14347 { # support for old ABI dumps
14348 if(not defined $Value_Old
14349 and substr($Value_New, 0, 2) eq "_Z") {
14350 $Value_Old = $Value_New;
14351 }
14352 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014353 if(defined $Value_Old)
14354 {
14355 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14356 if(defined $Value_New)
14357 {
14358 $Value_New = showVal($Value_New, $PType2_Id, 2);
14359 if($Value_Old ne $Value_New)
14360 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014361 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014362 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014363 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014364 "Old_Value"=>$Value_Old,
14365 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 }
14367 }
14368 else
14369 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014370 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014371 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014372 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014373 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014374 }
14375 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014376 elsif(defined $Value_New)
14377 {
14378 $Value_New = showVal($Value_New, $PType2_Id, 2);
14379 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14380 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014381 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014382 "New_Value"=>$Value_New );
14383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014384 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014385
14386 if($ChkRnmd)
14387 {
14388 if($PName1 and $PName2 and $PName1 ne $PName2
14389 and $PType1_Id!=-1 and $PType2_Id!=-1
14390 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14391 { # except unnamed "..." value list (Id=-1)
14392 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14393 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014394 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014395 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14396 "Old_Value"=>$PName1,
14397 "New_Value"=>$PName2,
14398 "New_Signature"=>get_Signature($Symbol, 2) );
14399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014402 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014403 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014405 foreach my $SubProblemType (keys(%SubProblems))
14406 { # add new problems, remove false alarms
14407 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14408 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014409
14410 # quals
14411 if($SubProblemType eq "Parameter_Type"
14412 or $SubProblemType eq "Parameter_Type_And_Size"
14413 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014415 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014416 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014417 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014418 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014419 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014420 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14421 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14422 }
14423 }
14424 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14425 {
14426 if(removedQual($Old_Value, $New_Value, "volatile")) {
14427 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014428 }
14429 }
14430 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14431 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14432 { # int to "int const"
14433 delete($SubProblems{$SubProblemType});
14434 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014435 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14437 { # "int const" to int
14438 delete($SubProblems{$SubProblemType});
14439 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014440 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14441 { # "const" to non-"const"
14442 if($RR==2) {
14443 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14444 }
14445 else {
14446 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14447 }
14448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014449 }
14450 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014451
14452 if($Level eq "Source")
14453 {
14454 foreach my $SubProblemType (keys(%SubProblems))
14455 {
14456 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14457 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14458
14459 if($SubProblemType eq "Parameter_Type")
14460 {
14461 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14462 delete($SubProblems{$SubProblemType});
14463 }
14464 }
14465 }
14466 }
14467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 foreach my $SubProblemType (keys(%SubProblems))
14469 { # modify/register problems
14470 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14471 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014472 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14473 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 my $NewProblemType = $SubProblemType;
14476 if($Old_Value eq "..." and $New_Value ne "...")
14477 { # change from "..." to "int"
14478 if($ParamPos1==0)
14479 { # ISO C requires a named argument before "..."
14480 next;
14481 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014482 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014483 }
14484 elsif($New_Value eq "..." and $Old_Value ne "...")
14485 { # change from "int" to "..."
14486 if($ParamPos2==0)
14487 { # ISO C requires a named argument before "..."
14488 next;
14489 }
14490 $NewProblemType = "Parameter_Became_VaList";
14491 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014492 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014493 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014494 {
14495 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014496 if($Arch1 eq "unknown"
14497 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014499 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 ($Arch1, $Arch2) = ("unknown", "unknown");
14501 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014502 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014503 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014504 { # real
14505 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14506 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14507 }
14508 else
14509 { # model
14510 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14511 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14512 }
14513 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014514 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014515 if($Conv1{"Method"} eq "stack")
14516 {
14517 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14518 $NewProblemType = "Parameter_Type_And_Stack";
14519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014521 elsif($Conv1{"Method"} eq "reg")
14522 {
14523 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14524 $NewProblemType = "Parameter_Type_And_Register";
14525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
14527 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014528 elsif($Conv1{"Method"} ne "unknown"
14529 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014530 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014531 if($Conv1{"Method"} eq "stack") {
14532 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014534 elsif($Conv1{"Method"} eq "register") {
14535 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 }
14537 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014538 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14539 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014541 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014542 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014543 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014544 "New_Signature"=>get_Signature($Symbol, 2) );
14545 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014546 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014547
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014548 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014549
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014550 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014551 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14552 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014553 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014554 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 {
14556 my $NewProblemType = $SubProblemType;
14557 if($SubProblemType eq "DataType_Size")
14558 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014559 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014560 { # stack has been affected
14561 $NewProblemType = "DataType_Size_And_Stack";
14562 }
14563 }
14564 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014565 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014566 }
14567 }
14568}
14569
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014570sub find_ParamPair_Pos_byName($$$)
14571{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014572 my ($Name, $Symbol, $LibVersion) = @_;
14573 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014575 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14576 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 {
14578 return $ParamPos;
14579 }
14580 }
14581 return "lost";
14582}
14583
14584sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14585{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014586 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014587 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014588 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014589 {
14590 next if($Order eq "backward" and $ParamPos>$MediumPos);
14591 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014592 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14593 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014594 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 push(@Positions, $ParamPos);
14596 }
14597 }
14598 return @Positions;
14599}
14600
14601sub getTypeIdByName($$)
14602{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014603 my ($TypeName, $LibVersion) = @_;
14604 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605}
14606
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014607sub diffTypes($$$)
14608{
14609 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14610 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14611 }
14612 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14613 { # skip recursive declarations
14614 return 0;
14615 }
14616
14617 pushType($_[0], $_[1], \@RecurTypes_Diff);
14618 my $Diff = diffTypes_I(@_);
14619 pop(@RecurTypes_Diff);
14620
14621 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14622}
14623
14624sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014626 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014627
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014628 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14629 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014630
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14632 { # equal types
14633 return 0;
14634 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014635 if($Type1_Pure{"Name"} eq "void")
14636 { # from void* to something
14637 return 0;
14638 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014639 if($Type2_Pure{"Name"} eq "void")
14640 { # from something to void*
14641 return 0;
14642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014643 if($Type1_Pure{"Name"}=~/\*/
14644 or $Type2_Pure{"Name"}=~/\*/)
14645 { # compared in detectTypeChange()
14646 return 0;
14647 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 my %FloatType = map {$_=>1} (
14650 "float",
14651 "double",
14652 "long double"
14653 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014654
14655 my $T1 = $Type1_Pure{"Type"};
14656 my $T2 = $Type2_Pure{"Type"};
14657
14658 if($T1 eq "Struct"
14659 and $T2 eq "Class")
14660 { # compare as data structures
14661 $T2 = "Struct";
14662 }
14663
14664 if($T1 eq "Class"
14665 and $T2 eq "Struct")
14666 { # compare as data structures
14667 $T1 = "Struct";
14668 }
14669
14670 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014671 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014672 if($T1 eq "Intrinsic"
14673 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 { # "int" to "enum"
14675 return 0;
14676 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014677 elsif($T2 eq "Intrinsic"
14678 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679 { # "enum" to "int"
14680 return 0;
14681 }
14682 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014683 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014684 # ...
14685 return 1;
14686 }
14687 }
14688 else
14689 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014690 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014691 {
14692 if($FloatType{$Type1_Pure{"Name"}}
14693 or $FloatType{$Type2_Pure{"Name"}})
14694 { # "float" to "double"
14695 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014696 if($Level eq "Source")
14697 { # Safe
14698 return 0;
14699 }
14700 else {
14701 return 1;
14702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014703 }
14704 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014705 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014706 {
14707 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14708 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014709 if(not @Membs1
14710 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014711 { # private
14712 return 0;
14713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014714 if($#Membs1!=$#Membs2)
14715 { # different number of elements
14716 return 1;
14717 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014718 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014719 {
14720 foreach my $Pos (@Membs1)
14721 { # compare elements by name and value
14722 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14723 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14724 { # different names
14725 return 1;
14726 }
14727 }
14728 }
14729 else
14730 {
14731 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014732 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014733 if($Level eq "Source")
14734 {
14735 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14736 { # different names
14737 return 1;
14738 }
14739 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014740
14741 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14742 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14743
14744 if($MT1{"Name"} ne $MT2{"Name"}
14745 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14746 {
14747 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14748 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14749
14750 if($PL1 ne $PL2)
14751 { # different pointer level
14752 return 1;
14753 }
14754
14755 # compare base types
14756 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14757 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14758
14759 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14760 { # different types
14761 return 1;
14762 }
14763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014764 }
14765 }
14766 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014767 else
14768 {
14769 # TODO: arrays, etc.
14770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771 }
14772 return 0;
14773}
14774
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014775sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014776{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014777 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014778 if(not $Type1_Id or not $Type2_Id) {
14779 return ();
14780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014781 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014782 my %Type1 = get_Type($Type1_Id, 1);
14783 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014784 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14785 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014786
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014787 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14788 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 +040014789
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014790 if(defined $UsedDump{1}{"DWARF"})
14791 {
14792 if($Type1_Pure{"Name"} eq "__unknown__"
14793 or $Type2_Pure{"Name"} eq "__unknown__"
14794 or $Type1_Base{"Name"} eq "__unknown__"
14795 or $Type2_Base{"Name"} eq "__unknown__")
14796 { # Error ABI dump
14797 return ();
14798 }
14799 }
14800
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014801 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14802 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014803 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14804 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14805 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14806 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14807 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14808 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14809 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014810 if($Type1{"Name"} eq $Type2{"Name"})
14811 {
14812 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14813 { # will be reported in mergeTypes() as typedef problem
14814 return ();
14815 }
14816 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14817 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14818 if(%Typedef_1 and %Typedef_2)
14819 {
14820 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14821 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14822 { # const Typedef
14823 return ();
14824 }
14825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014826 }
14827 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014829 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014830 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14831 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014832 {
14833 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14834 "Old_Value"=>$Type1_Base{"Name"},
14835 "New_Value"=>$Type2_Base{"Name"},
14836 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014837 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014838 }
14839 else
14840 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014841 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014842 { # format change
14843 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14844 "Old_Value"=>$Type1_Base{"Name"},
14845 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014846 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014847 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014848 }
14849 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14850 {
14851 %{$LocalProblems{$Prefix."_BaseType"}}=(
14852 "Old_Value"=>$Type1_Base{"Name"},
14853 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014854 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014855 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014856 }
14857 }
14858 }
14859 }
14860 elsif($Type1{"Name"} ne $Type2{"Name"})
14861 { # type change
14862 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14863 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014864 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 and $Type1_Pure{"Name"} eq "void")
14866 {
14867 %{$LocalProblems{"Return_Type_From_Void"}}=(
14868 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014869 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014871 elsif($Prefix eq "Return"
14872 and $Type2_Pure{"Name"} eq "void")
14873 {
14874 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14875 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014876 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014878 else
14879 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014880 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014881 and $Type1{"Size"} and $Type2{"Size"}
14882 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014883 {
14884 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14885 "Old_Value"=>$Type1{"Name"},
14886 "New_Value"=>$Type2{"Name"},
14887 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014888 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 }
14890 else
14891 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014892 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014893 { # format change
14894 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14895 "Old_Value"=>$Type1{"Name"},
14896 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014897 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014898 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014899 }
14900 elsif(tNameLock($Type1_Id, $Type2_Id))
14901 { # FIXME: correct this condition
14902 %{$LocalProblems{$Prefix."_Type"}}=(
14903 "Old_Value"=>$Type1{"Name"},
14904 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014905 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014906 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014907 }
14908 }
14909 }
14910 }
14911 }
14912 if($Type1_PLevel!=$Type2_PLevel)
14913 {
14914 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14915 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014917 if($Level eq "Source")
14918 {
14919 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 "Old_Value"=>$Type1_PLevel,
14921 "New_Value"=>$Type2_PLevel);
14922 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014923 else
14924 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014925 if($Type2_PLevel>$Type1_PLevel)
14926 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014927 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14928 "Old_Value"=>$Type1_PLevel,
14929 "New_Value"=>$Type2_PLevel);
14930 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014931 else
14932 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014933 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14934 "Old_Value"=>$Type1_PLevel,
14935 "New_Value"=>$Type2_PLevel);
14936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 }
14938 }
14939 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014940 if($Type1_Pure{"Type"} eq "Array"
14941 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 { # base_type[N] -> base_type[N]
14943 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014944 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014945 foreach my $SubProblemType (keys(%SubProblems))
14946 {
14947 $SubProblemType=~s/_Type/_BaseType/g;
14948 next if(defined $LocalProblems{$SubProblemType});
14949 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14950 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14951 }
14952 }
14953 }
14954 return %LocalProblems;
14955}
14956
14957sub tNameLock($$)
14958{
14959 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014960 my $Changed = 0;
14961 if(differentDumps("G"))
14962 { # different GCC versions
14963 $Changed = 1;
14964 }
14965 elsif(differentDumps("V"))
14966 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014967 if(not checkDump(1, "2.20")
14968 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014969 { # latest names update
14970 # 2.6: added restrict qualifier
14971 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014972 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014973 $Changed = 1;
14974 }
14975 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014976
14977 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14978 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14979
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014980 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14981 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14982
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014983 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014985 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014986 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014987 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014988 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014989 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014990 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014991 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014993 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14994 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14995 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014996 { # equal base types
14997 return 0;
14998 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014999
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015000 if(not checkDump(1, "2.13")
15001 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015002 { # broken array names in ABI dumps < 2.13
15003 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015004 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 return 0;
15006 }
15007 }
15008
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015009 if(not checkDump(1, "2.6")
15010 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015011 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015012 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015013 and $TN2=~/\brestrict\b/) {
15014 return 0;
15015 }
15016 }
15017
15018 if(not checkDump(1, "2.20")
15019 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015020 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015021 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15022 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015023 return 0;
15024 }
15025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015026 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015027 else
15028 {
15029 # typedef struct {...} type_t
15030 # typedef struct type_t {...} type_t
15031 if(index($TN1, " ".$TN2)!=-1)
15032 {
15033 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15034 return 0;
15035 }
15036 }
15037 if(index($TN2, " ".$TN1)!=-1)
15038 {
15039 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15040 return 0;
15041 }
15042 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015043
15044 if($TT1 eq "FuncPtr"
15045 and $TT2 eq "FuncPtr")
15046 {
15047 my $TN1_C = $TN1;
15048 my $TN2_C = $TN2;
15049
15050 $TN1_C=~s/\b(struct|union) //g;
15051 $TN2_C=~s/\b(struct|union) //g;
15052
15053 if($TN1_C eq $TN2_C) {
15054 return 0;
15055 }
15056 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015057 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015058
15059 my ($N1, $N2) = ($TN1, $TN2);
15060 $N1=~s/\b(struct|union) //g;
15061 $N2=~s/\b(struct|union) //g;
15062
15063 if($N1 eq $N2)
15064 { # QList<struct QUrl> and QList<QUrl>
15065 return 0;
15066 }
15067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015068 return 1;
15069}
15070
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015071sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015072{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015073 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015074 if(defined $Cache{"differentDumps"}{$Check}) {
15075 return $Cache{"differentDumps"}{$Check};
15076 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015077 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015078 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015079 if($Check eq "G")
15080 {
15081 if(getGccVersion(1) ne getGccVersion(2))
15082 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015083 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015084 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015085 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015086 if($Check eq "V")
15087 {
15088 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15089 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15090 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015091 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015092 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015094 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015095 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015096}
15097
15098sub formatVersion($$)
15099{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015100 my ($V, $Digits) = @_;
15101 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015102 return join(".", splice(@Elems, 0, $Digits));
15103}
15104
15105sub htmlSpecChars($)
15106{
15107 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015108 if(not $Str) {
15109 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15112 $Str=~s/</&lt;/g;
15113 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15114 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015115 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15116 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015117 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015118 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015119 $Str=~s/\n/<br\/>/g;
15120 $Str=~s/\"/&quot;/g;
15121 $Str=~s/\'/&#39;/g;
15122 return $Str;
15123}
15124
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015125sub xmlSpecChars($)
15126{
15127 my $Str = $_[0];
15128 if(not $Str) {
15129 return $Str;
15130 }
15131
15132 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15133 $Str=~s/</&lt;/g;
15134 $Str=~s/>/&gt;/g;
15135
15136 $Str=~s/\"/&quot;/g;
15137 $Str=~s/\'/&#39;/g;
15138
15139 return $Str;
15140}
15141
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015142sub xmlSpecChars_R($)
15143{
15144 my $Str = $_[0];
15145 if(not $Str) {
15146 return $Str;
15147 }
15148
15149 $Str=~s/&amp;/&/g;
15150 $Str=~s/&lt;/</g;
15151 $Str=~s/&gt;/>/g;
15152
15153 $Str=~s/&quot;/"/g;
15154 $Str=~s/&#39;/'/g;
15155
15156 return $Str;
15157}
15158
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015159sub black_name($)
15160{
15161 my $Name = $_[0];
15162 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15163}
15164
15165sub highLight_Signature($)
15166{
15167 my $Signature = $_[0];
15168 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15169}
15170
15171sub highLight_Signature_Italic_Color($)
15172{
15173 my $Signature = $_[0];
15174 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15175}
15176
15177sub separate_symbol($)
15178{
15179 my $Symbol = $_[0];
15180 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15181 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15182 ($Name, $Spec, $Ver) = ($1, $2, $3);
15183 }
15184 return ($Name, $Spec, $Ver);
15185}
15186
15187sub cut_f_attrs($)
15188{
15189 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15190 return $2;
15191 }
15192 return "";
15193}
15194
15195sub highLight_Signature_PPos_Italic($$$$$)
15196{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015197 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15198 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015199 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15200 my $Return = "";
15201 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15202 $Return = $2;
15203 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015204 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015206 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015207 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015208 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015209 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015210 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015211 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015212 }
15213 return $Signature;
15214 }
15215 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15216 $Begin.=" " if($Begin!~/ \Z/);
15217 $End = cut_f_attrs($Signature);
15218 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015219 my ($Short, $Params) = split_Signature($Signature);
15220 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015221 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015223 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 $Part=~s/\A\s+|\s+\Z//g;
15225 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15226 if($Part=~/\([\*]+(\w+)\)/i) {
15227 $ParamName = $1;#func-ptr
15228 }
15229 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15230 $ParamName = $1;
15231 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015232 if(not $ParamName)
15233 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 push(@Parts, $Part_Styled);
15235 next;
15236 }
15237 if($ItalicParams and not $TName_Tid{1}{$Part}
15238 and not $TName_Tid{2}{$Part})
15239 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015240 my $Style = "<i>$ParamName</i>";
15241
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015242 if($Param_Pos ne ""
15243 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015244 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015245 }
15246 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015247 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015249
15250 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015251 }
15252 $Part_Styled=~s/,(\w)/, $1/g;
15253 push(@Parts, $Part_Styled);
15254 }
15255 if(@Parts)
15256 {
15257 foreach my $Num (0 .. $#Parts)
15258 {
15259 if($Num==$#Parts)
15260 { # add ")" to the last parameter
15261 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15262 }
15263 elsif(length($Parts[$Num])<=45) {
15264 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15265 }
15266 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015267 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268 }
15269 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015270 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 }
15272 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015273 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015275 $Signature=~s!\[\]![&#160;]!g;
15276 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015277 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15278 if($SymbolVersion) {
15279 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15280 }
15281 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282}
15283
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015284sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015285{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015286 my $Signature = $_[0];
15287 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15288 {
15289 $Signature=~s/\A\Q$ShortName\E\(//g;
15290 cut_f_attrs($Signature);
15291 $Signature=~s/\)\Z//;
15292 return ($ShortName, $Signature);
15293 }
15294
15295 # error
15296 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015297}
15298
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015299sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015301 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015302 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015303 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15304 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015305 foreach my $Pos (0 .. length($Params) - 1)
15306 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015307 my $S = substr($Params, $Pos, 1);
15308 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015309 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015310 }
15311 if($S eq "," and
15312 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015313 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015314 if($Comma)
15315 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015316 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015317 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015318 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015319 }
15320 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015321 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322 }
15323 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015324 if(not $Sp)
15325 { # remove spaces
15326 foreach (@Parts)
15327 {
15328 s/\A //g;
15329 s/ \Z//g;
15330 }
15331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015332 return @Parts;
15333}
15334
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015335sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015336{
15337 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015338 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015339 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015340 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15341 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015342 $Center+=length($1);
15343 }
15344 foreach my $Pos (0 .. length($Sign)-1)
15345 {
15346 my $S = substr($Sign, $Pos, 1);
15347 if($S eq $Target)
15348 {
15349 if($B{"("}==$B{")"}
15350 and $B{"<"}==$B{">"}) {
15351 return $Center;
15352 }
15353 }
15354 if(defined $B{$S}) {
15355 $B{$S}+=1;
15356 }
15357 $Center+=1;
15358 }
15359 return 0;
15360}
15361
15362sub appendFile($$)
15363{
15364 my ($Path, $Content) = @_;
15365 return if(not $Path);
15366 if(my $Dir = get_dirname($Path)) {
15367 mkpath($Dir);
15368 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015369 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015370 print FILE $Content;
15371 close(FILE);
15372}
15373
15374sub writeFile($$)
15375{
15376 my ($Path, $Content) = @_;
15377 return if(not $Path);
15378 if(my $Dir = get_dirname($Path)) {
15379 mkpath($Dir);
15380 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015381 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015382 print FILE $Content;
15383 close(FILE);
15384}
15385
15386sub readFile($)
15387{
15388 my $Path = $_[0];
15389 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015390 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391 local $/ = undef;
15392 my $Content = <FILE>;
15393 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015394 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015395 $Content=~s/\r/\n/g;
15396 }
15397 return $Content;
15398}
15399
15400sub get_filename($)
15401{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015402 if(defined $Cache{"get_filename"}{$_[0]}) {
15403 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015404 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015405 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15406 return ($Cache{"get_filename"}{$_[0]}=$1);
15407 }
15408 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015409}
15410
15411sub get_dirname($)
15412{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015413 if(defined $Cache{"get_dirname"}{$_[0]}) {
15414 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015415 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015416 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15417 return ($Cache{"get_dirname"}{$_[0]}=$1);
15418 }
15419 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015420}
15421
15422sub separate_path($) {
15423 return (get_dirname($_[0]), get_filename($_[0]));
15424}
15425
15426sub esc($)
15427{
15428 my $Str = $_[0];
15429 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15430 return $Str;
15431}
15432
15433sub readLineNum($$)
15434{
15435 my ($Path, $Num) = @_;
15436 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015437 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015438 foreach (1 ... $Num) {
15439 <FILE>;
15440 }
15441 my $Line = <FILE>;
15442 close(FILE);
15443 return $Line;
15444}
15445
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015446sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015447{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015448 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015449 return () if(not $Path or not -f $Path);
15450 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015451 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15452 {
15453 foreach my $AttrVal (split(/;/, $1))
15454 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015455 if($AttrVal=~/(.+):(.+)/)
15456 {
15457 my ($Name, $Value) = ($1, $2);
15458 $Attributes{$Name} = $Value;
15459 }
15460 }
15461 }
15462 return \%Attributes;
15463}
15464
15465sub is_abs($) {
15466 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15467}
15468
15469sub get_abs_path($)
15470{ # abs_path() should NOT be called for absolute inputs
15471 # because it can change them
15472 my $Path = $_[0];
15473 if(not is_abs($Path)) {
15474 $Path = abs_path($Path);
15475 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015476 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477}
15478
15479sub get_OSgroup()
15480{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015481 my $N = $Config{"osname"};
15482 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015483 return "macos";
15484 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015485 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 return "bsd";
15487 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015488 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015489 return "beos";
15490 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015491 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015492 return "symbian";
15493 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015494 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015495 return "windows";
15496 }
15497 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015498 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015499 }
15500}
15501
15502sub getGccVersion($)
15503{
15504 my $LibVersion = $_[0];
15505 if($GCC_VERSION{$LibVersion})
15506 { # dump version
15507 return $GCC_VERSION{$LibVersion};
15508 }
15509 elsif($UsedDump{$LibVersion}{"V"})
15510 { # old-version dumps
15511 return "unknown";
15512 }
15513 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15514 if(not $GccVersion) {
15515 return "unknown";
15516 }
15517 return $GccVersion;
15518}
15519
15520sub showArch($)
15521{
15522 my $Arch = $_[0];
15523 if($Arch eq "arm"
15524 or $Arch eq "mips") {
15525 return uc($Arch);
15526 }
15527 return $Arch;
15528}
15529
15530sub getArch($)
15531{
15532 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015533
15534 if($TargetArch) {
15535 return $TargetArch;
15536 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015537 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015538 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 return $CPU_ARCH{$LibVersion};
15540 }
15541 elsif($UsedDump{$LibVersion}{"V"})
15542 { # old-version dumps
15543 return "unknown";
15544 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015545
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015546 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015547}
15548
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015549sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015550{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015551 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015552
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015553 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015554 if(getArch(1) ne getArch(2)
15555 or getArch(1) eq "unknown"
15556 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015557 { # don't show architecture in the header
15558 $ArchInfo="";
15559 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015560 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015561 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015562 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015563 }
15564 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015565 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015566 }
15567 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015568 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015569 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015570
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015571 my $V1 = $Descriptor{1}{"Version"};
15572 my $V2 = $Descriptor{2}{"Version"};
15573
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015574 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15575 {
15576 my $M1 = $UsedDump{1}{"M"};
15577 my $M2 = $UsedDump{2}{"M"};
15578
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015579 my $M1S = $M1;
15580 my $M2S = $M2;
15581
15582 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15583 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15584
15585 if($M1S eq $M2S
15586 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015587 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015588 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15589 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015590 }
15591 else
15592 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015593 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15594 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015595 }
15596 }
15597 else
15598 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015599 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015600 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015601 }
15602
15603 $Title .= $ArchInfo;
15604
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015606 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015607 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015608 $Title = "<h1>".$Title."</h1>\n";
15609 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610}
15611
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015612sub get_CheckedHeaders($)
15613{
15614 my $LibVersion = $_[0];
15615
15616 my @Headers = ();
15617
15618 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15619 {
15620 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015621
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015622 if(not is_target_header($File, $LibVersion)) {
15623 next;
15624 }
15625
15626 if(skipHeader($File, $LibVersion)) {
15627 next;
15628 }
15629
15630 push(@Headers, $Path);
15631 }
15632
15633 return @Headers;
15634}
15635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015636sub get_SourceInfo()
15637{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015638 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015639
15640 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015641 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015642 $CheckedHeaders = "<a name='Headers'></a>";
15643 if($OldStyle) {
15644 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15645 }
15646 else {
15647 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15648 }
15649 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015650 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 +040015651 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015652 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15653 my $Name = get_filename($Identity);
15654 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15655 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015656 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015657 $CheckedHeaders .= "</div>\n";
15658 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015659 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015660
15661 if(my @Sources = keys(%{$Registered_Sources{1}}))
15662 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015663 $CheckedSources = "<a name='Sources'></a>";
15664 if($OldStyle) {
15665 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15666 }
15667 else {
15668 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15669 }
15670 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015671 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15672 {
15673 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15674 my $Name = get_filename($Identity);
15675 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15676 $CheckedSources .= $Name.$Comment."<br/>\n";
15677 }
15678 $CheckedSources .= "</div>\n";
15679 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15680 }
15681
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015682 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015683 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015684 $CheckedLibs = "<a name='Libs'></a>";
15685 if($OldStyle) {
15686 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15687 }
15688 else {
15689 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15690 }
15691 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15692 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015693 $CheckedLibs .= $Library."<br/>\n";
15694 }
15695 $CheckedLibs .= "</div>\n";
15696 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015697 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015698
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015699 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15700}
15701
15702sub get_ObjTitle()
15703{
15704 if(defined $UsedDump{1}{"DWARF"}) {
15705 return "Objects";
15706 }
15707 else {
15708 return ucfirst($SLIB_TYPE)." Libraries";
15709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015710}
15711
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015712sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015713{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015714 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015715 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015716
15717 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015718 {
15719 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015720 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015722 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015723 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015724 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015725 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015726
15727 if($Severity ne $TargetSeverity) {
15728 next;
15729 }
15730
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015731 if($Kinds_Target{$Kind}{$Target}) {
15732 next;
15733 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015734
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 $Kinds_Target{$Kind}{$Target} = 1;
15736 $Type_Problems_Count += 1;
15737 }
15738 }
15739 }
15740 return $Type_Problems_Count;
15741}
15742
15743sub get_Summary($)
15744{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015745 my $Level = $_[0];
15746 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015747 $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 +040015748 %{$RESULT{$Level}} = (
15749 "Problems"=>0,
15750 "Warnings"=>0,
15751 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015753 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015754 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015755 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 {
15757 if(not defined $CompatRules{$Level}{$Kind})
15758 { # unknown rule
15759 if(not $UnknownRules{$Level}{$Kind})
15760 { # only one warning
15761 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15762 $UnknownRules{$Level}{$Kind}=1;
15763 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015764 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015765 }
15766 }
15767 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015768 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15769 {
15770 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15771 {
15772 if(not defined $CompatRules{$Level}{$Kind})
15773 { # unknown rule
15774 if(not $UnknownRules{$Level}{$Kind})
15775 { # only one warning
15776 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15777 $UnknownRules{$Level}{$Kind}=1;
15778 }
15779 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15780 }
15781 }
15782 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015783 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015784 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015785 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015786 {
15787 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15788 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015789 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015790 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015791 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015792 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015793 $Added += 1;
15794 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015795 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796 {
15797 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015798 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 }
15800 else
15801 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015802 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015803 $I_Other += 1;
15804 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015805 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 $I_Problems_High += 1;
15807 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015808 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015809 $I_Problems_Medium += 1;
15810 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015811 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015812 $I_Problems_Low += 1;
15813 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015814 if(($Severity ne "Low" or $StrictCompat)
15815 and $Severity ne "Safe") {
15816 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015817 }
15818 }
15819 }
15820 }
15821 }
15822 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015823
15824 my %MethodTypeIndex = ();
15825
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015826 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015828 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15829 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015830 {
15831 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15832 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015833 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15834 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015835 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015836 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15837 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015838
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015839 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15840 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015841 next;
15842 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015843 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15844 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15845
15846 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015847
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015848 if(($Severity ne "Low" or $StrictCompat)
15849 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015850 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015851 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015852 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015853 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015854 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015855 }
15856 }
15857 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015858 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015861 }
15862 }
15863 }
15864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015865
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015866 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15867 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15868 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15869 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015870
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015871 # changed and removed public symbols
15872 my $SCount = keys(%{$CheckedSymbols{$Level}});
15873 if($ExtendedCheck)
15874 { # don't count external_func_0 for constants
15875 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015876 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015877 if($SCount)
15878 {
15879 my %Weight = (
15880 "High" => 100,
15881 "Medium" => 50,
15882 "Low" => 25
15883 );
15884 foreach (keys(%{$TotalAffected{$Level}})) {
15885 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015886 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015887 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015888 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015889 else {
15890 $RESULT{$Level}{"Affected"} = 0;
15891 }
15892
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015893 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15894 if($RESULT{$Level}{"Affected"}>=100) {
15895 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015896 }
15897
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015898 $RESULT{$Level}{"Problems"} += $Removed;
15899 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015900 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015901 if($StrictCompat) {
15902 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15903 }
15904 else {
15905 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015907
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015908 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015909 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015910 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015911 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015912 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015913 if($Severity eq "Safe")
15914 {
15915 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015916 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015917 elsif($Severity eq "Low")
15918 {
15919 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015920 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015921 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015922 }
15923
15924 if($C_Problems_Low)
15925 {
15926 if($StrictCompat) {
15927 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15928 }
15929 else {
15930 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015931 }
15932 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015933 if($RESULT{$Level}{"Problems"}
15934 and $RESULT{$Level}{"Affected"}) {
15935 $RESULT{$Level}{"Verdict"} = "incompatible";
15936 }
15937 else {
15938 $RESULT{$Level}{"Verdict"} = "compatible";
15939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015940
15941 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15942 if(not $TotalTypes)
15943 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015944 $TotalTypes = keys(%{$TName_Tid{1}});
15945 }
15946
15947 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15948 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15949
15950 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15951
15952 if($ReportFormat eq "xml")
15953 { # XML
15954 # test info
15955 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15956 $TestInfo .= " <version1>\n";
15957 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015958 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015959 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15960 $TestInfo .= " </version1>\n";
15961
15962 $TestInfo .= " <version2>\n";
15963 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015964 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015965 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15966 $TestInfo .= " </version2>\n";
15967 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15968
15969 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015970 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015971 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015972 $TestResults .= " <headers>\n";
15973 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15974 {
15975 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15976 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15977 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15978 }
15979 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015980 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015981
15982 if(my @Sources = keys(%{$Registered_Sources{1}}))
15983 {
15984 $TestResults .= " <sources>\n";
15985 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15986 {
15987 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15988 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15989 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15990 }
15991 $TestResults .= " </sources>\n";
15992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993
15994 $TestResults .= " <libs>\n";
15995 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15996 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015997 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015998 $TestResults .= " <name>$Library</name>\n";
15999 }
16000 $TestResults .= " </libs>\n";
16001
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016002 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016003 $TestResults .= " <types>".$TotalTypes."</types>\n";
16004
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016005 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16006 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016007 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16008
16009 # problem summary
16010 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16011 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16012
16013 $Problem_Summary .= " <problems_with_types>\n";
16014 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16015 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16016 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16017 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16018 $Problem_Summary .= " </problems_with_types>\n";
16019
16020 $Problem_Summary .= " <problems_with_symbols>\n";
16021 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16022 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16023 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016024 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016025 $Problem_Summary .= " </problems_with_symbols>\n";
16026
16027 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016028 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016029 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016030
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016031 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16032
16033 return ($TestInfo.$TestResults.$Problem_Summary, "");
16034 }
16035 else
16036 { # HTML
16037 # test info
16038 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016039 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016040
16041 if($TargetComponent eq "library") {
16042 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16043 }
16044 else {
16045 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016047
16048 my (@VInf1, @VInf2, $AddTestInfo) = ();
16049 if($Arch1 ne "unknown"
16050 and $Arch2 ne "unknown")
16051 { # CPU arch
16052 if($Arch1 eq $Arch2)
16053 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016054 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016055 }
16056 else
16057 { # go to the version number
16058 push(@VInf1, showArch($Arch1));
16059 push(@VInf2, showArch($Arch2));
16060 }
16061 }
16062 if($GccV1 ne "unknown"
16063 and $GccV2 ne "unknown"
16064 and $OStarget ne "windows")
16065 { # GCC version
16066 if($GccV1 eq $GccV2)
16067 { # go to the separate section
16068 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16069 }
16070 else
16071 { # go to the version number
16072 push(@VInf1, "gcc ".$GccV1);
16073 push(@VInf2, "gcc ".$GccV2);
16074 }
16075 }
16076 # show long version names with GCC version and CPU architecture name (if different)
16077 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16078 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16079 $TestInfo .= $AddTestInfo;
16080 #if($COMMON_LANGUAGE{1}) {
16081 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16082 #}
16083 if($ExtendedCheck) {
16084 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016086 if($JoinReport)
16087 {
16088 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016089 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016090 }
16091 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016092 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016093 }
16094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016095 $TestInfo .= "</table>\n";
16096
16097 # test results
16098 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016099 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016100
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016101 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016102 {
16103 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16104 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16105 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016106
16107 if(my @Sources = keys(%{$Registered_Sources{1}}))
16108 {
16109 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16110 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016112
16113 if(not $ExtendedCheck)
16114 {
16115 my $Libs_Link = "0";
16116 $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 +040016117 $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 +040016118 }
16119
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016120 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016121
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016122 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016123 if($JoinReport) {
16124 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16125 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016126
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016127 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016128
16129 $TestResults .= "<tr><th>Compatibility</th>\n";
16130 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16131 {
16132 my $Cl = "incompatible";
16133 if($BC_Rate>=90) {
16134 $Cl = "warning";
16135 }
16136 elsif($BC_Rate>=80) {
16137 $Cl = "almost_compatible";
16138 }
16139
16140 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016141 }
16142 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016143 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016144 }
16145 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146 $TestResults .= "</table>\n";
16147
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149 # problem summary
16150 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16153
16154 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016155 if($Added>0)
16156 {
16157 if($JoinReport) {
16158 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16159 }
16160 else {
16161 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16162 }
16163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016165 $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 +040016166
16167 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016168 if($Removed>0)
16169 {
16170 if($JoinReport) {
16171 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16172 }
16173 else {
16174 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16175 }
16176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016177 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016178 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016179 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016180
16181 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016182 $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 +040016183 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016184 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016185 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016186
16187 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 $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 +040016189 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016190 $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 +040016191
16192 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016193 $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 +040016194 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016195 $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 +040016196
16197 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016198 $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 +040016199 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016200 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016201 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202
16203 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016204 $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 +040016205 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016206 $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 +040016207
16208 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 $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 +040016210 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016211 $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 +040016212
16213 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016214 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16215 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016218 $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 +040016219
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016220 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016221 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016222 {
16223 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016224 $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 +030016225 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016226 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016227
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016228 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 {
16230 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016231 $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 +030016232 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016234
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016235 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016236 {
16237 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016238 $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 +030016239 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016240 }
16241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016242 $META_DATA .= "tool_version:$TOOL_VERSION";
16243 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016245 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16246 }
16247}
16248
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016249sub getStyle($$$)
16250{
16251 my ($Subj, $Act, $Num) = @_;
16252 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016253 "Added"=>"new",
16254 "Removed"=>"failed",
16255 "Safe"=>"passed",
16256 "Low"=>"warning",
16257 "Medium"=>"failed",
16258 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016259 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016260
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016261 if($Num>0) {
16262 return " class='".$Style{$Act}."'";
16263 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016264
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016265 return "";
16266}
16267
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268sub show_number($)
16269{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016271 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016272 my $Num = cut_off_number($_[0], 2, 0);
16273 if($Num eq "0")
16274 {
16275 foreach my $P (3 .. 7)
16276 {
16277 $Num = cut_off_number($_[0], $P, 1);
16278 if($Num ne "0") {
16279 last;
16280 }
16281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282 }
16283 if($Num eq "0") {
16284 $Num = $_[0];
16285 }
16286 return $Num;
16287 }
16288 return $_[0];
16289}
16290
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016293 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016294 if($num!~/\./)
16295 {
16296 $num .= ".";
16297 foreach (1 .. $digs_to_cut-1) {
16298 $num .= "0";
16299 }
16300 }
16301 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16302 {
16303 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16304 $num .= "0";
16305 }
16306 }
16307 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16308 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16309 }
16310 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 if($z) {
16312 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016314 return $num;
16315}
16316
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016317sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016318{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016319 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016320 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016321
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016322 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016323 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16324 {
16325 my $Header = $Constants{1}{$Constant}{"Header"};
16326 if(not $Header)
16327 { # added
16328 $Header = $Constants{2}{$Constant}{"Header"}
16329 }
16330
16331 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16332 {
16333 if(not defined $CompatRules{$Level}{$Kind}) {
16334 next;
16335 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016336 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016337 next;
16338 }
16339 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016341 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343 if($ReportFormat eq "xml")
16344 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016345 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016346 {
16347 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016348 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016349 {
16350 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016351 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16352 {
16353 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16354 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16355 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016356
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016357 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16358 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16359 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016360 if($Overcome) {
16361 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16362 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016363 $CHANGED_CONSTANTS .= " </problem>\n";
16364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016365 $CHANGED_CONSTANTS .= " </constant>\n";
16366 }
16367 $CHANGED_CONSTANTS .= " </header>\n";
16368 }
16369 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16370 }
16371 else
16372 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016373 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016374 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 {
16376 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016377 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016378 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016379 my $Report = "";
16380
16381 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16382 {
16383 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16384 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016385 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016386 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016387 }
16388 if($Report)
16389 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016390 $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 +030016391 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016392 $Report = insertIDs($Report);
16393 }
16394 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016395 }
16396 $CHANGED_CONSTANTS .= "<br/>\n";
16397 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016398 if($CHANGED_CONSTANTS)
16399 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016400 my $Title = "Problems with Constants, $TargetSeverity Severity";
16401 if($TargetSeverity eq "Safe")
16402 { # Safe Changes
16403 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016404 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016405 if($OldStyle) {
16406 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16407 }
16408 else {
16409 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16410 }
16411 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016412 }
16413 }
16414 return $CHANGED_CONSTANTS;
16415}
16416
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016417sub getTitle($$$)
16418{
16419 my ($Header, $Library, $NameSpace) = @_;
16420 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016421
16422 # if($Library and $Library!~/\.\w+\Z/) {
16423 # $Library .= " (.$LIB_EXT)";
16424 # }
16425
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016426 if($Header and $Library)
16427 {
16428 $Title .= "<span class='h_name'>$Header</span>";
16429 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16430 }
16431 elsif($Library) {
16432 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16433 }
16434 elsif($Header) {
16435 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16436 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016437
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016438 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016439 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016441
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016442 return $Title;
16443}
16444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016445sub get_Report_Added($)
16446{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016447 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016448 my $ADDED_INTERFACES = "";
16449 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016450 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016451 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016452 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
16456 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16457 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016458 if($Level eq "Source" and $ReportFormat eq "html")
16459 { # do not show library name in HTML report
16460 $DyLib = "";
16461 }
16462 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016463 }
16464 }
16465 }
16466 if($ReportFormat eq "xml")
16467 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016468 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 {
16470 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016471 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 {
16473 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016474 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016475 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16476 }
16477 $ADDED_INTERFACES .= " </library>\n";
16478 }
16479 $ADDED_INTERFACES .= " </header>\n";
16480 }
16481 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16482 }
16483 else
16484 { # HTML
16485 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016486 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016488 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016489 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016490 my %NameSpaceSymbols = ();
16491 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016492 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016493 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016494 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016496 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16497 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016498 foreach my $Interface (@SortedInterfaces)
16499 {
16500 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016501 my $Signature = get_Signature($Interface, 2);
16502 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016503 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016505 if($Interface=~/\A(_Z|\?)/)
16506 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016507 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016508 $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 +040016509 }
16510 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016511 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016512 }
16513 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016514 else
16515 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016517 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 }
16519 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016520 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016521 }
16522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016524 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 }
16527 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016528 if($ADDED_INTERFACES)
16529 {
16530 my $Anchor = "<a name='Added'></a>";
16531 if($JoinReport) {
16532 $Anchor = "<a name='".$Level."_Added'></a>";
16533 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016534 if($OldStyle) {
16535 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16536 }
16537 else {
16538 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16539 }
16540 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 }
16542 }
16543 return $ADDED_INTERFACES;
16544}
16545
16546sub get_Report_Removed($)
16547{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016549 my $REMOVED_INTERFACES = "";
16550 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016551 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016552 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016553 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016555 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016557 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16558 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 if($Level eq "Source" and $ReportFormat eq "html")
16560 { # do not show library name in HTML report
16561 $DyLib = "";
16562 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016563 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 }
16565 }
16566 }
16567 if($ReportFormat eq "xml")
16568 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016569 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016570 {
16571 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016572 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016573 {
16574 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016575 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16576 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 }
16578 $REMOVED_INTERFACES .= " </library>\n";
16579 }
16580 $REMOVED_INTERFACES .= " </header>\n";
16581 }
16582 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16583 }
16584 else
16585 { # HTML
16586 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016587 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016589 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 my %NameSpaceSymbols = ();
16592 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016593 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016594 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016595 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16598 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016599 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016600 {
16601 $Removed_Number += 1;
16602 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016603 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016605 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016606 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016607 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016608 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016609 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016610 $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 +040016611 }
16612 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016613 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016614 }
16615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016616 else
16617 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016619 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 }
16621 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016622 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016623 }
16624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 }
16626 }
16627 $REMOVED_INTERFACES .= "<br/>\n";
16628 }
16629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016630 if($REMOVED_INTERFACES)
16631 {
16632 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16633 if($JoinReport) {
16634 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16635 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016636 if($OldStyle) {
16637 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16638 }
16639 else {
16640 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16641 }
16642
16643 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 }
16645 }
16646 return $REMOVED_INTERFACES;
16647}
16648
16649sub getXmlParams($$)
16650{
16651 my ($Content, $Problem) = @_;
16652 return "" if(not $Content or not $Problem);
16653 my %XMLparams = ();
16654 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16655 {
16656 my $Macro = "\@".lc($Attr);
16657 if($Content=~/\Q$Macro\E/) {
16658 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16659 }
16660 }
16661 my @PString = ();
16662 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016663 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 }
16665 if(@PString) {
16666 return " ".join(" ", @PString);
16667 }
16668 else {
16669 return "";
16670 }
16671}
16672
16673sub addMarkup($)
16674{
16675 my $Content = $_[0];
16676 # auto-markup
16677 $Content=~s/\n[ ]*//; # spaces
16678 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16679 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016680 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016681 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16682 if($Content=~/\ANOTE:/)
16683 { # notes
16684 $Content=~s!(NOTE):!<b>$1</b>:!g;
16685 }
16686 else {
16687 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16688 }
16689 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16690 my @Keywords = (
16691 "void",
16692 "const",
16693 "static",
16694 "restrict",
16695 "volatile",
16696 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016697 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 );
16699 my $MKeys = join("|", @Keywords);
16700 foreach (@Keywords) {
16701 $MKeys .= "|non-".$_;
16702 }
16703 $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 +040016704
16705 # Markdown
16706 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16707 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016708 return $Content;
16709}
16710
16711sub applyMacroses($$$$)
16712{
16713 my ($Level, $Kind, $Content, $Problem) = @_;
16714 return "" if(not $Content or not $Problem);
16715 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16716 $Content = addMarkup($Content);
16717 # macros
16718 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16719 {
16720 my $Macro = "\@".lc($Attr);
16721 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016722 if(not defined $Value
16723 or $Value eq "") {
16724 next;
16725 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016726
16727 if(index($Content, $Macro)==-1) {
16728 next;
16729 }
16730
16731 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16732 and $Kind!~/_Type_/
16733 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016735 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016736 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 $Value = black_name($Value);
16738 }
16739 elsif($Value=~/\s/) {
16740 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16741 }
16742 elsif($Value=~/\A\d+\Z/
16743 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16744 { # bits to bytes
16745 if($Value % $BYTE_SIZE)
16746 { # bits
16747 if($Value==1) {
16748 $Value = "<b>".$Value."</b> bit";
16749 }
16750 else {
16751 $Value = "<b>".$Value."</b> bits";
16752 }
16753 }
16754 else
16755 { # bytes
16756 $Value /= $BYTE_SIZE;
16757 if($Value==1) {
16758 $Value = "<b>".$Value."</b> byte";
16759 }
16760 else {
16761 $Value = "<b>".$Value."</b> bytes";
16762 }
16763 }
16764 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016765 else
16766 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 $Value = "<b>".htmlSpecChars($Value)."</b>";
16768 }
16769 $Content=~s/\Q$Macro\E/$Value/g;
16770 }
16771
16772 if($Content=~/(\A|[^\@\w])\@\w/)
16773 {
16774 if(not $IncompleteRules{$Level}{$Kind})
16775 { # only one warning
16776 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16777 $IncompleteRules{$Level}{$Kind} = 1;
16778 }
16779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016780 return $Content;
16781}
16782
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016783sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016785 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016786 my $INTERFACE_PROBLEMS = "";
16787 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016788
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016789 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016790 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016791 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16792 if($SV and defined $CompatProblems{$Level}{$SN}) {
16793 next;
16794 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016795 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16796 my $DyLib = $Symbol_Library{1}{$Symbol};
16797 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16798 { # Symbol with Version
16799 $DyLib = $Symbol_Library{1}{$VSym};
16800 }
16801 if(not $DyLib)
16802 { # const global data
16803 $DyLib = "";
16804 }
16805 if($Level eq "Source" and $ReportFormat eq "html")
16806 { # do not show library name in HTML report
16807 $DyLib = "";
16808 }
16809
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
16812 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016815 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16816 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016818 if($Severity eq $TargetSeverity)
16819 {
16820 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16821 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016822 }
16823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 }
16825 }
16826 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 if($ReportFormat eq "xml")
16829 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016830 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016831 {
16832 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 {
16835 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016836 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16837 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016838 {
16839 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016840 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016841 {
16842 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16843 {
16844 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016845 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016847 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16848 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16849 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16850 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16851 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016852 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16853 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016855 $INTERFACE_PROBLEMS .= " </problem>\n";
16856 }
16857 }
16858 $INTERFACE_PROBLEMS .= " </symbol>\n";
16859 }
16860 $INTERFACE_PROBLEMS .= " </library>\n";
16861 }
16862 $INTERFACE_PROBLEMS .= " </header>\n";
16863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016864 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016865 }
16866 else
16867 { # HTML
16868 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016871 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 my (%NameSpaceSymbols, %NewSignature) = ();
16874 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016875 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016876 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016877 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016880 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 +040016881 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 my $Signature = get_Signature($Symbol, 1);
16884 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016886 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016888 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016890 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016891 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016892 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016893 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 }
16895 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16896 {
16897 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016898 $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 +040016899 $ProblemNum += 1;
16900 $ProblemsNum += 1;
16901 }
16902 }
16903 }
16904 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016906 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016907 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016908 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016909 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016911
16912 if($NameSpace)
16913 {
16914 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16915 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016916 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016917
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016918 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
16919 if($OldStyle) {
16920 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
16921 }
16922 else {
16923 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
16924 }
16925 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016926 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016927
16928 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016929 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016930 if($NameSpace) {
16931 $NSign = cut_Namespace($NSign, $NameSpace);
16932 }
16933 $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 +040016934 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016935
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 if($Symbol=~/\A(_Z|\?)/) {
16937 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16938 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016939
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016940 $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 +040016941 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016942 }
16943 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016944 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 }
16946 }
16947 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016948
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016949 if($INTERFACE_PROBLEMS)
16950 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016951 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16952 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16953 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 { # Safe Changes
16955 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016957 if($OldStyle) {
16958 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
16959 }
16960 else {
16961 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
16962 }
16963 $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 +040016964 }
16965 }
16966 return $INTERFACE_PROBLEMS;
16967}
16968
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016969sub cut_Namespace($$)
16970{
16971 my ($N, $Ns) = @_;
16972 $N=~s/\b\Q$Ns\E:://g;
16973 return $N;
16974}
16975
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016976sub get_Report_TypeProblems($$)
16977{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016978 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016979 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016980
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016981 my %ReportMap = ();
16982 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016983
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016984 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016986 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
16987
16988 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016989 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016990 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016992 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016993 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016994
16995 if($Severity eq $TargetSeverity)
16996 {
16997 $ReportMap{$HeaderName}{$TypeName} = 1;
16998 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017003
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 if($ReportFormat eq "xml")
17005 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017006 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 {
17008 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017009 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017010 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017011 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017012 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017013 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017014 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017015 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017016 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017017 $Kinds_Locations{$Kind}{$Location} = 1;
17018
17019 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17020 if($Kinds_Target{$Kind}{$Target}) {
17021 next;
17022 }
17023 $Kinds_Target{$Kind}{$Target} = 1;
17024
17025 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017026 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17027 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17028 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17029 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17030 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017031 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17032 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017034 $TYPE_PROBLEMS .= " </problem>\n";
17035 }
17036 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017037 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17038 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017039 $TYPE_PROBLEMS .= showVTables($TypeName);
17040 }
17041 $TYPE_PROBLEMS .= " </type>\n";
17042 }
17043 $TYPE_PROBLEMS .= " </header>\n";
17044 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017045 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017046 }
17047 else
17048 { # HTML
17049 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017050 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017051 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017052 my (%NameSpace_Type) = ();
17053 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017054 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017055 }
17056 foreach my $NameSpace (sort keys(%NameSpace_Type))
17057 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017058 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017059 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 +040017060 foreach my $TypeName (@SortedTypes)
17061 {
17062 my $ProblemNum = 1;
17063 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017064 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017065
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017066 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017068 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017070 $Kinds_Locations{$Kind}{$Location} = 1;
17071
17072 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17073 if($Kinds_Target{$Kind}{$Target}) {
17074 next;
17075 }
17076 $Kinds_Target{$Kind}{$Target} = 1;
17077
17078 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017079 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17080 {
17081 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017082 $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 +040017083 $ProblemNum += 1;
17084 $ProblemsNum += 1;
17085 }
17086 }
17087 }
17088 $ProblemNum -= 1;
17089 if($TYPE_REPORT)
17090 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017091 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017093 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 $ShowVTables = showVTables($TypeName);
17095 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017096
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017097 my $ShowType = show_Type($TypeName, 1, 1);
17098
17099 if($NameSpace)
17100 {
17101 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17102 $ShowType = cut_Namespace($ShowType, $NameSpace);
17103 $Affected = cut_Namespace($Affected, $NameSpace);
17104 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17105 }
17106
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017107 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17108 if($OldStyle) {
17109 $TYPE_PROBLEMS .= " ($ProblemNum)";
17110 }
17111 else {
17112 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17113 }
17114 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017115 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17116 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17117 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17118 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 }
17120 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017121 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 }
17123 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 if($TYPE_PROBLEMS)
17126 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017127 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17128 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017129 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 { # Safe Changes
17131 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017132 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017133 if($OldStyle) {
17134 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17135 }
17136 else {
17137 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17138 }
17139 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140 }
17141 }
17142 return $TYPE_PROBLEMS;
17143}
17144
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017145sub show_Type($$$)
17146{
17147 my ($Name, $Html, $LibVersion) = @_;
17148 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17149 $TType = lc($TType);
17150 if($TType=~/struct|union|enum/) {
17151 $Name=~s/\A\Q$TType\E //g;
17152 }
17153 if($Html) {
17154 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17155 }
17156 else {
17157 $Name = $TType." ".$Name;
17158 }
17159 return $Name;
17160}
17161
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017162sub get_Anchor($$$)
17163{
17164 my ($Kind, $Level, $Severity) = @_;
17165 if($JoinReport)
17166 {
17167 if($Severity eq "Safe") {
17168 return "Other_".$Level."_Changes_In_".$Kind."s";
17169 }
17170 else {
17171 return $Kind."_".$Level."_Problems_".$Severity;
17172 }
17173 }
17174 else
17175 {
17176 if($Severity eq "Safe") {
17177 return "Other_Changes_In_".$Kind."s";
17178 }
17179 else {
17180 return $Kind."_Problems_".$Severity;
17181 }
17182 }
17183}
17184
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017185sub showVTables($)
17186{
17187 my $TypeName = $_[0];
17188 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017189 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 if(defined $Type1{"VTable"}
17191 and keys(%{$Type1{"VTable"}}))
17192 {
17193 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017194 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017195 if(defined $Type2{"VTable"}
17196 and keys(%{$Type2{"VTable"}}))
17197 {
17198 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17199 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017200 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017202 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17203 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 }
17205 my $VTABLES = "";
17206 if($ReportFormat eq "xml")
17207 { # XML
17208 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017209 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017210 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017211 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017212 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17213 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017214 $VTABLES .= " </entry>\n";
17215 }
17216 $VTABLES .= " </vtable>\n\n";
17217 }
17218 else
17219 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017220 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017221 $VTABLES .= "<tr><th>Offset</th>";
17222 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017224 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017225 {
17226 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017227
17228 my $E1 = $Entries{$Index}{"E1"};
17229 my $E2 = $Entries{$Index}{"E2"};
17230
17231 if($E1 ne $E2
17232 and $E1!~/ 0x/
17233 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017235 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017237 $Color1 = " class='failed'";
17238 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239 }
17240 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017241 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017242 }
17243 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017244 $VTABLES .= "<tr><th>".$Index."</th>\n";
17245 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17246 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247 }
17248 $VTABLES .= "</table><br/>\n";
17249 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017250 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017251 }
17252 return $VTABLES;
17253 }
17254 }
17255 return "";
17256}
17257
17258sub simpleVEntry($)
17259{
17260 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017261 if(not defined $VEntry
17262 or $VEntry eq "") {
17263 return "";
17264 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017265
17266 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017267 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17268 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17269 if($VEntry=~/\A_ZThn.+\Z/) {
17270 $VEntry = "non-virtual thunk";
17271 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017272 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017273 # support for old GCC versions
17274 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17275 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17276 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17278 return $VEntry;
17279}
17280
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017281sub adjustParamPos($$$)
17282{
17283 my ($Pos, $Symbol, $LibVersion) = @_;
17284 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17285 {
17286 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17287 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17288 {
17289 return $Pos-1;
17290 }
17291
17292 return $Pos;
17293 }
17294
17295 return undef;
17296}
17297
17298sub getParamPos($$$)
17299{
17300 my ($Name, $Symbol, $LibVersion) = @_;
17301
17302 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17303 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17304 {
17305 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17306 foreach (keys(%{$Info->{"Param"}}))
17307 {
17308 if($Info->{"Param"}{$_}{"name"} eq $Name)
17309 {
17310 return $_;
17311 }
17312 }
17313 }
17314
17315 return undef;
17316}
17317
17318sub getParamName($)
17319{
17320 my $Loc = $_[0];
17321 $Loc=~s/\->.*//g;
17322 return $Loc;
17323}
17324
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017325sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017327 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017328
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017329 my $LIMIT = 10;
17330 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017331 $LIMIT = $AffectLimit;
17332 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017333
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017334 my @Kinds = sort keys(%{$Kinds_Locations});
17335 my %KLocs = ();
17336 foreach my $Kind (@Kinds)
17337 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017338 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 +030017339 $KLocs{$Kind} = \@Locs;
17340 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017341
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017342 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017343 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017344 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017345 if(index($Symbol, "_Z")==0
17346 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017347 { # duplicated problems for C2 constructors, D2 and D0 destructors
17348 next;
17349 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017350
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017351 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017352 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017353 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017354 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017355 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017356 next;
17357 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017358
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017359 if(index($Symbol, "\@")!=-1
17360 or index($Symbol, "\$")!=-1)
17361 {
17362 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17363
17364 if($Level eq "Source")
17365 { # remove symbol version
17366 $Symbol = $SN;
17367 }
17368
17369 if($SV and defined $CompatProblems{$Level}{$SN}
17370 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17371 { # duplicated problems for versioned symbols
17372 next;
17373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017374 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017375
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017376 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017377 if($Type_Name ne $Target_TypeName) {
17378 next;
17379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017381 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017382 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017383 }
17384 }
17385 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017386
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017387 %KLocs = (); # clear
17388
17389 my %SymSel = ();
17390 my $Num = 0;
17391 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017392 {
17393 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17394 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017395 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017396 {
17397 $SymSel{$Symbol}{"Loc"} = $Loc;
17398 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017399 last LOOP;
17400 }
17401 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017402
17403 $Num += 1;
17404
17405 if($Num>=$LIMIT) {
17406 last;
17407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017408 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017410 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 if($ReportFormat eq "xml")
17413 { # XML
17414 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017415
17416 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017417 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017418 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017419 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017420
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017421 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017422 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017423
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017424 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017425 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017426 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017427 $Target .= " param=\"$PName\"";
17428 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017429 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017430 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017431 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017433 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017434 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017436
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017437 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017438 $Target .= " field=\"$1\"";
17439 }
17440
17441 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017442 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017443 $Affected .= " </symbol>\n";
17444 }
17445 $Affected .= " </affected>\n";
17446 }
17447 else
17448 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017449 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017450 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017451 my $Kind = $SymSel{$Symbol}{"Kind"};
17452 my $Loc = $SymSel{$Symbol}{"Loc"};
17453
17454 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017455 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017456 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017457 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17458
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017459 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017460 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017462
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017463 if(keys(%SymLocKind)>$LIMIT) {
17464 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017466
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017467 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017468 if($Affected)
17469 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017470 my $Num = keys(%SymLocKind);
17471 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017472 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017473 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 }
17475 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017477 return $Affected;
17478}
17479
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017480sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017481{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017482 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017483 if($L2=~/\A(retval|this)\b/
17484 and $L1!~/\A(retval|this)\b/)
17485 {
17486 if($L1!~/\-\>/) {
17487 return 1;
17488 }
17489 elsif($L2=~/\-\>/) {
17490 return 1;
17491 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017492 }
17493 return 0;
17494}
17495
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017496sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017497{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017498 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017499
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017500 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017501
17502 my $Location_I = $Location;
17503 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017505 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017506
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017507 if($Kind eq "Overridden_Virtual_Method"
17508 or $Kind eq "Overridden_Virtual_Method_B") {
17509 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17510 }
17511 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17512 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017513 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17514
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017515 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17516 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017517 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17518 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017520 if($ClassName eq $Problem{"Type_Name"}) {
17521 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17522 }
17523 else {
17524 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17525 }
17526 }
17527 else
17528 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017529 my $TypeID = undef;
17530
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017531 if($Location=~/retval/)
17532 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017533 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017534 push(@Sentence, "Field \'".$Location."\' in return value");
17535 }
17536 else {
17537 push(@Sentence, "Return value");
17538 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017539
17540 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017541 }
17542 elsif($Location=~/this/)
17543 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017544 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017545 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17546 }
17547 else {
17548 push(@Sentence, "\'this\' pointer");
17549 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017550
17551 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 }
17553 else
17554 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017555
17556 my $PName = getParamName($Location);
17557 my $PPos = getParamPos($PName, $Symbol, 1);
17558
17559 if(index($Location, "->")!=-1) {
17560 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017561 }
17562 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017563 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017564 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017565 if($PName) {
17566 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017567 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017568
17569 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17570 }
17571
17572 if($Location!~/this/)
17573 {
17574 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017575 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017576 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017577 push(@Sentence, "(pointer)");
17578 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017579 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017580 push(@Sentence, "(reference)");
17581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017582 }
17583 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017585 if($Location eq "this") {
17586 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17587 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017588 else
17589 {
17590 my $Location_T = $Location;
17591 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17592
17593 my $TypeID_Problem = $TypeID;
17594 if($Location_T) {
17595 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17596 }
17597
17598 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17599 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17600 }
17601 else {
17602 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017604 }
17605 }
17606 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017607 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017608 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 +040017609 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017610
17611 my $Sent = join(" ", @Sentence);
17612
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017613 $Sent=~s/->/./g;
17614
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017615 if($ReportFormat eq "xml")
17616 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017617 $Sent=~s/'//g;
17618 }
17619
17620 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017621}
17622
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017623sub getFieldType($$$)
17624{
17625 my ($Location, $TypeId, $LibVersion) = @_;
17626
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017627 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017628
17629 foreach my $Name (@Fields)
17630 {
17631 my %Info = get_BaseType($TypeId, $LibVersion);
17632
17633 foreach my $Pos (keys(%{$Info{"Memb"}}))
17634 {
17635 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17636 {
17637 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17638 last;
17639 }
17640 }
17641 }
17642
17643 return $TypeId;
17644}
17645
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017646sub get_XmlSign($$)
17647{
17648 my ($Symbol, $LibVersion) = @_;
17649 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17650 my $Report = "";
17651 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17652 {
17653 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017654 my $Type = $Info->{"Param"}{$Pos}{"type"};
17655 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 foreach my $Typedef (keys(%ChangedTypedef))
17657 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017658 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17659 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017661 }
17662 $Report .= " <param pos=\"$Pos\">\n";
17663 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017664 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017665 $Report .= " </param>\n";
17666 }
17667 if(my $Return = $Info->{"Return"})
17668 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017669 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017670 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017671 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017672 $Report .= " </retval>\n";
17673 }
17674 return $Report;
17675}
17676
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017677sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017678{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017679 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017680 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017681 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017682 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017683 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17684 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017685 next;
17686 }
17687 $Report .= " <symbol name=\"$Symbol\">\n";
17688 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017689 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017690 {
17691 if(defined $CompleteSignature{1}{$Symbol}
17692 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17693 {
17694 $P1 = get_XmlSign($Symbol, 1);
17695 $S1 = get_Signature($Symbol, 1);
17696 }
17697 elsif($Symbol=~/\A(_Z|\?)/) {
17698 $S1 = $tr_name{$Symbol};
17699 }
17700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017701 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017702 {
17703 if(defined $CompleteSignature{2}{$Symbol}
17704 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17705 {
17706 $P2 = get_XmlSign($Symbol, 2);
17707 $S2 = get_Signature($Symbol, 2);
17708 }
17709 elsif($Symbol=~/\A(_Z|\?)/) {
17710 $S2 = $tr_name{$Symbol};
17711 }
17712 }
17713 if($S1)
17714 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017715 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017716 $Report .= $P1;
17717 $Report .= " </old>\n";
17718 }
17719 if($S2 and $S2 ne $S1)
17720 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017721 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017722 $Report .= $P2;
17723 $Report .= " </new>\n";
17724 }
17725 $Report .= " </symbol>\n";
17726 }
17727 $Report .= "</symbols_info>\n";
17728 return $Report;
17729}
17730
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017731sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017732{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017733 my ($Level, $Report) = @_;
17734 if($ReportFormat eq "xml") {
17735 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017736 }
17737 if($StdOut)
17738 { # --stdout option
17739 print STDOUT $Report;
17740 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017741 else
17742 {
17743 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017744 mkpath(get_dirname($RPath));
17745
17746 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17747 print REPORT $Report;
17748 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017749 }
17750}
17751
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017752sub getReport($)
17753{
17754 my $Level = $_[0];
17755 if($ReportFormat eq "xml")
17756 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017757 if($Level eq "Join")
17758 {
17759 my $Report = "<reports>\n";
17760 $Report .= getReport("Binary");
17761 $Report .= getReport("Source");
17762 $Report .= "</reports>\n";
17763 return $Report;
17764 }
17765 else
17766 {
17767 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17768 my ($Summary, $MetaData) = get_Summary($Level);
17769 $Report .= $Summary."\n";
17770 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17771 $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 +040017772
17773 # additional symbols info (if needed)
17774 # $Report .= get_Report_SymbolsInfo($Level);
17775
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017776 $Report .= "</report>\n";
17777 return $Report;
17778 }
17779 }
17780 else
17781 { # HTML
17782 my $CssStyles = readModule("Styles", "Report.css");
17783 my $JScripts = readModule("Scripts", "Sections.js");
17784 if($Level eq "Join")
17785 {
17786 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17787 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017788 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017789 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17790 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 +040017791 my ($BSummary, $BMetaData) = get_Summary("Binary");
17792 my ($SSummary, $SMetaData) = get_Summary("Source");
17793 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 +030017794 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017795 <br/>
17796 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017797 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17798 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017799 </div>";
17800 $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>";
17801 $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 +030017802 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017803 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017804 return $Report;
17805 }
17806 else
17807 {
17808 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017809 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17810 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17811 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 +040017812 if($Level eq "Binary")
17813 {
17814 if(getArch(1) eq getArch(2)
17815 and getArch(1) ne "unknown") {
17816 $Description .= " on ".showArch(getArch(1));
17817 }
17818 }
17819 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 +030017820 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017821 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17822 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17823 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017824 $Report .= "</div>\n<br/><br/><br/>\n";
17825 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017826 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017827 return $Report;
17828 }
17829 }
17830}
17831
17832sub createReport()
17833{
17834 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017835 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017836 writeReport("Join", getReport("Join"));
17837 }
17838 elsif($DoubleReport)
17839 { # default
17840 writeReport("Binary", getReport("Binary"));
17841 writeReport("Source", getReport("Source"));
17842 }
17843 elsif($BinaryOnly)
17844 { # --binary
17845 writeReport("Binary", getReport("Binary"));
17846 }
17847 elsif($SourceOnly)
17848 { # --source
17849 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017850 }
17851}
17852
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017853sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017854{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017855 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017856
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017857 $Footer .= "<hr/>\n";
17858 $Footer .= "<div class='footer' align='right'>";
17859 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17860 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017861 $Footer .= "<br/>\n";
17862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017863 return $Footer;
17864}
17865
17866sub get_Report_Problems($$)
17867{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017868 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017869
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017870 my $Report = get_Report_TypeProblems($Severity, $Level);
17871 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017872 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017873 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017874
17875 if($Severity eq "Low" or $Severity eq "Safe") {
17876 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017877 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017879 if($ReportFormat eq "html")
17880 {
17881 if($Report)
17882 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017883 if($JoinReport)
17884 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017885 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017886 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17887 }
17888 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017889 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017891 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017892 else
17893 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017894 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017895 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17896 }
17897 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017898 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017900 }
17901 }
17902 }
17903 return $Report;
17904}
17905
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017906sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017907{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017908 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017909
17910 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17911 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17912 $Head .= "<head>\n";
17913 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17914 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17915 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17916 $Head .= "<title>$Title</title>\n";
17917 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17918 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17919 $Head .= "</head>\n";
17920
17921 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017922}
17923
17924sub insertIDs($)
17925{
17926 my $Text = $_[0];
17927 while($Text=~/CONTENT_ID/)
17928 {
17929 if(int($Content_Counter)%2) {
17930 $ContentID -= 1;
17931 }
17932 $Text=~s/CONTENT_ID/c_$ContentID/;
17933 $ContentID += 1;
17934 $Content_Counter += 1;
17935 }
17936 return $Text;
17937}
17938
17939sub checkPreprocessedUnit($)
17940{
17941 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017942 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017943 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017944 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017945
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017946 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017947 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017948 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017949 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017950 chomp($Line);
17951 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017952 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017953 $CurHeader = path_format($1, $OSgroup);
17954 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017955 $CurClass = "";
17956
17957 if(index($CurHeader, $TMP_DIR)==0) {
17958 next;
17959 }
17960
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017961 if(substr($CurHeaderName, 0, 1) eq "<")
17962 { # <built-in>, <command-line>, etc.
17963 $CurHeaderName = "";
17964 $CurHeader = "";
17965 }
17966
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017967 if($ExtraInfo)
17968 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017969 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017970 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17971 }
17972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017973 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017974 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017975 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017976 if($CurHeaderName)
17977 {
17978 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17979 and not $Registered_Headers{$Version}{$CurHeader})
17980 { # not a target
17981 next;
17982 }
17983 if(not is_target_header($CurHeaderName, 1)
17984 and not is_target_header($CurHeaderName, 2))
17985 { # user-defined header
17986 next;
17987 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017988 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017989 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017990
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017991 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017992 {
17993 my ($Name, $Value) = ($1, $2);
17994 if(not $Constants{$Version}{$Name}{"Access"})
17995 {
17996 $Constants{$Version}{$Name}{"Access"} = "public";
17997 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017998 if($CurHeaderName) {
17999 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18000 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018001 }
18002 }
18003 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18004 $Constants{$Version}{$1}{"Access"} = "private";
18005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018006 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018007 else
18008 {
18009 if(defined $ExtraDump)
18010 {
18011 if($Line=~/(\w+)\s*\(/)
18012 { # functions
18013 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18014 }
18015 #elsif($Line=~/(\w+)\s*;/)
18016 #{ # data
18017 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18018 #}
18019 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18020 $CurClass = $2;
18021 }
18022 }
18023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018024 }
18025 close(PREPROC);
18026 foreach my $Constant (keys(%{$Constants{$Version}}))
18027 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018028 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18029 {
18030 delete($Constants{$Version}{$Constant});
18031 next;
18032 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018033 if(not $ExtraDump and ($Constant=~/_h\Z/i
18034 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018035 { # skip
18036 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018037 }
18038 else {
18039 delete($Constants{$Version}{$Constant}{"Access"});
18040 }
18041 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018042 if($Debug)
18043 {
18044 mkpath($DEBUG_PATH{$Version});
18045 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018047}
18048
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018049sub uncoverConstant($$)
18050{
18051 my ($LibVersion, $Constant) = @_;
18052 return "" if(not $LibVersion or not $Constant);
18053 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18054 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18055 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18056 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018057
18058 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018059 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018060 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18061 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018062 {
18063 push(@RecurConstant, $Constant);
18064 my $Uncovered = uncoverConstant($LibVersion, $Value);
18065 if($Uncovered ne "") {
18066 $Value = $Uncovered;
18067 }
18068 pop(@RecurConstant);
18069 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018070
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018071 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018072 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018073 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18074 }
18075 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18076}
18077
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018078sub simpleConstant($$)
18079{
18080 my ($LibVersion, $Value) = @_;
18081 if($Value=~/\W/)
18082 {
18083 my $Value_Copy = $Value;
18084 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18085 {
18086 my $Word = $1;
18087 if($Value!~/$Word\s*\(/)
18088 {
18089 my $Val = uncoverConstant($LibVersion, $Word);
18090 if($Val ne "")
18091 {
18092 $Value=~s/\b$Word\b/$Val/g;
18093 }
18094 }
18095 }
18096 }
18097 return $Value;
18098}
18099
18100sub computeValue($)
18101{
18102 my $Value = $_[0];
18103
18104 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18105 return $1;
18106 }
18107
18108 if($Value=~/\A[\d\-\+()]+\Z/) {
18109 return eval($Value);
18110 }
18111
18112 return $Value;
18113}
18114
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018115my %IgnoreConstant = map {$_=>1} (
18116 "VERSION",
18117 "VERSIONCODE",
18118 "VERNUM",
18119 "VERS_INFO",
18120 "PATCHLEVEL",
18121 "INSTALLPREFIX",
18122 "VBUILD",
18123 "VPATCH",
18124 "VMINOR",
18125 "BUILD_STRING",
18126 "BUILD_TIME",
18127 "PACKAGE_STRING",
18128 "PRODUCTION",
18129 "CONFIGURE_COMMAND",
18130 "INSTALLDIR",
18131 "BINDIR",
18132 "CONFIG_FILE_PATH",
18133 "DATADIR",
18134 "EXTENSION_DIR",
18135 "INCLUDE_PATH",
18136 "LIBDIR",
18137 "LOCALSTATEDIR",
18138 "SBINDIR",
18139 "SYSCONFDIR",
18140 "RELEASE",
18141 "SOURCE_ID",
18142 "SUBMINOR",
18143 "MINOR",
18144 "MINNOR",
18145 "MINORVERSION",
18146 "MAJOR",
18147 "MAJORVERSION",
18148 "MICRO",
18149 "MICROVERSION",
18150 "BINARY_AGE",
18151 "INTERFACE_AGE",
18152 "CORE_ABI",
18153 "PATCH",
18154 "COPYRIGHT",
18155 "TIMESTAMP",
18156 "REVISION",
18157 "PACKAGE_TAG",
18158 "PACKAGEDATE",
18159 "NUMVERSION",
18160 "Release",
18161 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018162);
18163
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018164sub constantFilter($$$)
18165{
18166 my ($Name, $Value, $Level) = @_;
18167
18168 if($Level eq "Binary")
18169 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018170 if($Name=~/_t\Z/)
18171 { # __malloc_ptr_t
18172 return 1;
18173 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018174 foreach (keys(%IgnoreConstant))
18175 {
18176 if($Name=~/(\A|_)$_(_|\Z)/)
18177 { # version
18178 return 1;
18179 }
18180 if(/\A[A-Z].*[a-z]\Z/)
18181 {
18182 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18183 { # version
18184 return 1;
18185 }
18186 }
18187 }
18188 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18189 { # version
18190 return 1;
18191 }
18192 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18193 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18194 return 1;
18195 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018196
18197 if($Value=~/\A["'].*['"]/i)
18198 { # string
18199 return 0;
18200 }
18201
18202 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18203 { # static int gcry_pth_init
18204 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018205 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018206 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018207 return 1;
18208 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018209 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018210 { # foo(p)
18211 return 1;
18212 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018213 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018214 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018215 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018216 return 1;
18217 }
18218 }
18219
18220 return 0;
18221}
18222
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018223sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018224{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018225 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018226 foreach my $Constant (keys(%{$Constants{1}}))
18227 {
18228 if($SkipConstants{1}{$Constant})
18229 { # skipped by the user
18230 next;
18231 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018232
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018233 if(my $Header = $Constants{1}{$Constant}{"Header"})
18234 {
18235 if(not is_target_header($Header, 1)
18236 and not is_target_header($Header, 2))
18237 { # user-defined header
18238 next;
18239 }
18240 }
18241 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018242 next;
18243 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018244
18245 my $Old_Value = uncoverConstant(1, $Constant);
18246
18247 if(constantFilter($Constant, $Old_Value, $Level))
18248 { # separate binary and source problems
18249 next;
18250 }
18251
18252 if(not defined $Constants{2}{$Constant}{"Value"})
18253 { # removed
18254 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18255 "Target"=>$Constant,
18256 "Old_Value"=>$Old_Value );
18257 next;
18258 }
18259
18260 if($Constants{2}{$Constant}{"Value"} eq "")
18261 { # empty value
18262 # TODO: implement a rule
18263 next;
18264 }
18265
18266 my $New_Value = uncoverConstant(2, $Constant);
18267
18268 my $Old_Value_Pure = $Old_Value;
18269 my $New_Value_Pure = $New_Value;
18270
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018271 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18272 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18273 $New_Value_Pure=~s/(\W)\s+/$1/g;
18274 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018276 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018278 if($New_Value_Pure ne $Old_Value_Pure)
18279 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018280 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18281 { # complex values
18282 next;
18283 }
18284 if(computeValue($Old_Value) eq computeValue($New_Value))
18285 { # expressions
18286 next;
18287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018288 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18289 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18290 next;
18291 }
18292 if($Old_Value eq "0" and $New_Value eq "NULL")
18293 { # 0 => NULL
18294 next;
18295 }
18296 if($Old_Value eq "NULL" and $New_Value eq "0")
18297 { # NULL => 0
18298 next;
18299 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018300 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018301 "Target"=>$Constant,
18302 "Old_Value"=>$Old_Value,
18303 "New_Value"=>$New_Value );
18304 }
18305 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018306
18307 foreach my $Constant (keys(%{$Constants{2}}))
18308 {
18309 if(not defined $Constants{1}{$Constant}{"Value"})
18310 {
18311 if($SkipConstants{2}{$Constant})
18312 { # skipped by the user
18313 next;
18314 }
18315
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018316 if(my $Header = $Constants{2}{$Constant}{"Header"})
18317 {
18318 if(not is_target_header($Header, 1)
18319 and not is_target_header($Header, 2))
18320 { # user-defined header
18321 next;
18322 }
18323 }
18324 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018325 next;
18326 }
18327
18328 my $New_Value = uncoverConstant(2, $Constant);
18329 if(not defined $New_Value or $New_Value eq "") {
18330 next;
18331 }
18332
18333 if(constantFilter($Constant, $New_Value, $Level))
18334 { # separate binary and source problems
18335 next;
18336 }
18337
18338 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18339 "Target"=>$Constant,
18340 "New_Value"=>$New_Value );
18341 }
18342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018343}
18344
18345sub convert_integer($)
18346{
18347 my $Value = $_[0];
18348 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018349 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018350 return hex($Value);
18351 }
18352 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018353 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018354 return oct($Value);
18355 }
18356 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018357 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018358 return oct($Value);
18359 }
18360 else {
18361 return $Value;
18362 }
18363}
18364
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018365sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018366{
18367 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018368 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018369 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018370 {
18371 if($LibVersion==1)
18372 {
18373 printMsg("WARNING", "checking headers only");
18374 $CheckHeadersOnly = 1;
18375 }
18376 else {
18377 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18378 }
18379 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018380
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018381 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018382 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018383 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018384
18385 if($CheckUndefined)
18386 {
18387 my %UndefinedLibs = ();
18388
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018389 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18390
18391 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018392 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018393 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018394 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018395 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018396 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018397 if($Symbol_Library{$LibVersion}{$Symbol}
18398 or $DepSymbol_Library{$LibVersion}{$Symbol})
18399 { # exported by target library
18400 next;
18401 }
18402 if(index($Symbol, '@')!=-1)
18403 { # exported default symbol version (@@)
18404 $Symbol=~s/\@/\@\@/;
18405 if($Symbol_Library{$LibVersion}{$Symbol}
18406 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18407 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018408 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018409 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018410 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18411 $UndefinedLibs{$Path} = 1;
18412 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018413 }
18414 }
18415 }
18416 if($ExtraInfo)
18417 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018418 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018419 {
18420 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018421 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018422 foreach (@Paths)
18423 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018424 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018425 my ($Dir, $Name) = separate_path($_);
18426
18427 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018428 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018429 }
18430
18431 $Name = parse_libname($Name, "name", $OStarget);
18432 $Name=~s/\Alib//;
18433
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018434 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018435 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018436
18437 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18438 {
18439 $LibString = " -L".esc($Dir).$LibString;
18440 }
18441
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018442 writeFile($ExtraInfo."/libs-string", $LibString);
18443 }
18444 }
18445 }
18446
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018447 if($ExtraInfo) {
18448 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18449 }
18450
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018451 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018452 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018453 if($#LibPaths!=-1)
18454 {
18455 if(not keys(%{$Symbol_Library{$LibVersion}}))
18456 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018457 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018458 printMsg("WARNING", "checking headers only");
18459 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018460 }
18461 }
18462 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018463
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018464 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018465 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018466}
18467
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018468my %Prefix_Lib_Map=(
18469 # symbols for autodetecting library dependencies (by prefix)
18470 "pthread_" => ["libpthread"],
18471 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18472 "cairo_" => ["libcairo"],
18473 "gtk_" => ["libgtk-x11-2.0"],
18474 "atk_" => ["libatk-1.0"],
18475 "gdk_" => ["libgdk-x11-2.0"],
18476 "gl" => ["libGL"],
18477 "glu" => ["libGLU"],
18478 "popt" => ["libpopt"],
18479 "Py" => ["libpython"],
18480 "jpeg_" => ["libjpeg"],
18481 "BZ2_" => ["libbz2"],
18482 "Fc" => ["libfontconfig"],
18483 "Xft" => ["libXft"],
18484 "SSL_" => ["libssl"],
18485 "sem_" => ["libpthread"],
18486 "snd_" => ["libasound"],
18487 "art_" => ["libart_lgpl_2"],
18488 "dbus_g" => ["libdbus-glib-1"],
18489 "GOMP_" => ["libgomp"],
18490 "omp_" => ["libgomp"],
18491 "cms" => ["liblcms"]
18492);
18493
18494my %Pattern_Lib_Map=(
18495 "SL[a-z]" => ["libslang"]
18496);
18497
18498my %Symbol_Lib_Map=(
18499 # symbols for autodetecting library dependencies (by name)
18500 "pow" => "libm",
18501 "fmod" => "libm",
18502 "sin" => "libm",
18503 "floor" => "libm",
18504 "cos" => "libm",
18505 "dlopen" => "libdl",
18506 "deflate" => "libz",
18507 "inflate" => "libz",
18508 "move_panel" => "libpanel",
18509 "XOpenDisplay" => "libX11",
18510 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018511 "clock_gettime" => "librt",
18512 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018513);
18514
18515sub find_SymbolLibs($$)
18516{
18517 my ($LibVersion, $Symbol) = @_;
18518
18519 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18520 { # debug symbols
18521 return ();
18522 }
18523
18524 my %Paths = ();
18525
18526 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18527 {
18528 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18529 $Paths{$Path} = 1;
18530 }
18531 }
18532
18533 if(my $SymbolPrefix = getPrefix($Symbol))
18534 {
18535 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18536 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18537 }
18538
18539 if(not keys(%Paths))
18540 {
18541 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18542 {
18543 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18544 {
18545 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18546 $Paths{$Path} = 1;
18547 }
18548 }
18549 }
18550 }
18551
18552 if(not keys(%Paths))
18553 {
18554 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18555 {
18556 if($Symbol=~/\A$Prefix/)
18557 {
18558 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18559 {
18560 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18561 $Paths{$Path} = 1;
18562 }
18563 }
18564 }
18565 }
18566 }
18567
18568 if(not keys(%Paths))
18569 {
18570 if($SymbolPrefix)
18571 { # try to find a library by symbol prefix
18572 if($SymbolPrefix eq "inotify" and
18573 index($Symbol, "\@GLIBC")!=-1)
18574 {
18575 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18576 $Paths{$Path} = 1;
18577 }
18578 }
18579 else
18580 {
18581 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18582 $Paths{$Path} = 1;
18583 }
18584 }
18585 }
18586 }
18587
18588 if(my @Paths = keys(%Paths)) {
18589 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18590 }
18591 }
18592 return keys(%Paths);
18593}
18594
18595sub get_LibPath_Prefix($$)
18596{
18597 my ($LibVersion, $Prefix) = @_;
18598
18599 $Prefix = lc($Prefix);
18600 $Prefix=~s/[_]+\Z//g;
18601
18602 foreach ("-2", "2", "-1", "1", "")
18603 { # libgnome-2.so
18604 # libxml2.so
18605 # libdbus-1.so
18606 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18607 return $Path;
18608 }
18609 }
18610 return "";
18611}
18612
18613sub getPrefix($)
18614{
18615 my $Str = $_[0];
18616 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18617 { # XmuValidArea: Xmu
18618 return $1;
18619 }
18620 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18621 { # snfReadFont: snf
18622 return $1;
18623 }
18624 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18625 { # XRRTimes: XRR
18626 return $1;
18627 }
18628 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18629 { # H5HF_delete: H5
18630 return $1;
18631 }
18632 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18633 { # alarm_event_add: alarm_
18634 return $1;
18635 }
18636 elsif($Str=~/\A(([a-z])\2{1,})/i)
18637 { # ffopen
18638 return $1;
18639 }
18640 return "";
18641}
18642
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018643sub getSymbolSize($$)
18644{ # size from the shared library
18645 my ($Symbol, $LibVersion) = @_;
18646 return 0 if(not $Symbol);
18647 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18648 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18649 {
18650 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18651 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18652 {
18653 if($Size<0) {
18654 return -$Size;
18655 }
18656 }
18657 }
18658 return 0;
18659}
18660
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018661sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018662{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18663 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018664 my ($Name, $Type) = @_;
18665
18666 # single
18667 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018668 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018669 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018670 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018671 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018672
18673 # double
18674 if($Name=~/$DEFAULT_STD_PARMS/)
18675 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018676 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018677 {
18678 my ($ShortName, $FuncParams) = split_Signature($Name);
18679
18680 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18681 {
18682 if(index($FParam, "<")!=-1)
18683 {
18684 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18685 my $FParam_N = canonifyName($FParam, "T");
18686 if($FParam_N ne $FParam) {
18687 $Name=~s/\Q$FParam\E/$FParam_N/g;
18688 }
18689 }
18690 }
18691 }
18692 elsif($Type eq "T")
18693 {
18694 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18695
18696 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018697 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018698 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018699 my $FParam = $TParams[0];
18700 foreach my $Pos (1 .. $#TParams)
18701 {
18702 my $TParam = $TParams[$Pos];
18703 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18704 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18705 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018706 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018707 }
18708 }
18709 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018710 if($Type eq "S") {
18711 return formatName($Name, "S");
18712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018713 return $Name;
18714}
18715
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018716sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018717{
18718 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018719 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018720 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018721 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018722 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018723 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018724 next if($tr_name{$Symbol});
18725 $Symbol=~s/[\@\$]+(.*)\Z//;
18726 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018727 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018728 elsif(index($Symbol, "?")==0)
18729 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018730 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018731 }
18732 else
18733 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018734 $tr_name{$Symbol} = $Symbol;
18735 $mangled_name_gcc{$Symbol} = $Symbol;
18736 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018737 }
18738 }
18739 if($#MnglNames1 > -1)
18740 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018741 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018742 foreach my $MnglName (@MnglNames1)
18743 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018744 if(my $Unmangled = pop(@UnmangledNames))
18745 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018746 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018747 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18748 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018750 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018751 and $tr_name{$MnglName}=~/vtable for (.+)/)
18752 { # bind class name and v-table symbol
18753 my $ClassName = $1;
18754 $ClassVTable{$ClassName} = $MnglName;
18755 $VTableClass{$MnglName} = $ClassName;
18756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018757 }
18758 }
18759 }
18760 if($#MnglNames2 > -1)
18761 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018762 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018763 foreach my $MnglName (@MnglNames2)
18764 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018765 if(my $Unmangled = pop(@UnmangledNames))
18766 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018767 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018768 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018770 }
18771 }
18772 return \%tr_name;
18773}
18774
18775sub link_symbol($$$)
18776{
18777 my ($Symbol, $RunWith, $Deps) = @_;
18778 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18779 return 1;
18780 }
18781 if($Deps eq "+Deps")
18782 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018783 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018784 return 1;
18785 }
18786 }
18787 return 0;
18788}
18789
18790sub link_symbol_internal($$$)
18791{
18792 my ($Symbol, $RunWith, $Where) = @_;
18793 return 0 if(not $Where or not $Symbol);
18794 if($Where->{$RunWith}{$Symbol})
18795 { # the exact match by symbol name
18796 return 1;
18797 }
18798 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18799 { # indirect symbol version, i.e.
18800 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018801 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802 if($Where->{$RunWith}{$VSym}) {
18803 return 1;
18804 }
18805 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018806 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018807 if($Sym and $Ver)
18808 { # search for the symbol with the same version
18809 # or without version
18810 if($Where->{$RunWith}{$Sym})
18811 { # old: foo@v|foo@@v
18812 # new: foo
18813 return 1;
18814 }
18815 if($Where->{$RunWith}{$Sym."\@".$Ver})
18816 { # old: foo|foo@@v
18817 # new: foo@v
18818 return 1;
18819 }
18820 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18821 { # old: foo|foo@v
18822 # new: foo@@v
18823 return 1;
18824 }
18825 }
18826 return 0;
18827}
18828
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018829sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018830{
18831 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018832 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018833 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018834 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018835 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018836 my $NM = get_CmdPath("nm");
18837 if(not $NM) {
18838 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018839 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018840 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018841 while(<APP>)
18842 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018843 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844 push(@Imported, $1);
18845 }
18846 }
18847 close(APP);
18848 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018849 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018850 {
18851 my $DumpBinCmd = get_CmdPath("dumpbin");
18852 if(not $DumpBinCmd) {
18853 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18854 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018855 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018856 while(<APP>)
18857 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018858 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18859 push(@Imported, $1);
18860 }
18861 }
18862 close(APP);
18863 }
18864 else
18865 {
18866 my $ReadelfCmd = get_CmdPath("readelf");
18867 if(not $ReadelfCmd) {
18868 exitStatus("Not_Found", "can't find \"readelf\"");
18869 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018870 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018871 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018872 while(<APP>)
18873 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018874 if(defined $symtab)
18875 { # do nothing with symtab
18876 if(index($_, "'.dynsym'")!=-1)
18877 { # dynamic table
18878 $symtab = undef;
18879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018880 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018881 elsif(index($_, "'.symtab'")!=-1)
18882 { # symbol table
18883 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018884 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018885 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018887 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18888 if($Ndx eq "UND")
18889 { # only imported symbols
18890 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 }
18892 }
18893 }
18894 close(APP);
18895 }
18896 return @Imported;
18897}
18898
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018899my %ELF_BIND = map {$_=>1} (
18900 "WEAK",
18901 "GLOBAL"
18902);
18903
18904my %ELF_TYPE = map {$_=>1} (
18905 "FUNC",
18906 "IFUNC",
18907 "OBJECT",
18908 "COMMON"
18909);
18910
18911my %ELF_VIS = map {$_=>1} (
18912 "DEFAULT",
18913 "PROTECTED"
18914);
18915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018917{ # read the line of 'readelf' output corresponding to the symbol
18918 my @Info = split(/\s+/, $_[0]);
18919 # Num: Value Size Type Bind Vis Ndx Name
18920 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018921 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 shift(@Info); # spaces
18923 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018924
18925 if($#Info==7)
18926 { # UND SYMBOL (N)
18927 if($Info[7]=~/\(\d+\)/) {
18928 pop(@Info);
18929 }
18930 }
18931
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018932 if($#Info!=6)
18933 { # other lines
18934 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018936 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018937 return () if(not defined $ELF_BIND{$Info[3]});
18938 return () if(not defined $ELF_VIS{$Info[4]});
18939 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18940 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18941 return ();
18942 }
18943 if($OStarget eq "symbian")
18944 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18945 if(index($Info[6], "_._.absent_export_")!=-1)
18946 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18947 return ();
18948 }
18949 $Info[6]=~s/\@.+//g; # remove version
18950 }
18951 if(index($Info[2], "0x") == 0)
18952 { # size == 0x3d158
18953 $Info[2] = hex($Info[2]);
18954 }
18955 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018956}
18957
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018959{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018960 my ($LibVersion, $Name) = @_;
18961 return "" if(not $LibVersion or not $Name);
18962 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18963 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018964 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018965 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18966}
18967
18968sub get_LibPath_I($$)
18969{
18970 my ($LibVersion, $Name) = @_;
18971 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018972 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018973 if(-f $Name)
18974 { # absolute path
18975 return $Name;
18976 }
18977 else
18978 { # broken
18979 return "";
18980 }
18981 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018982 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018984 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018985 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018986 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018987 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018988 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018989 }
18990 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18991 { # ldconfig default paths
18992 return $DefaultPath;
18993 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018994 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018995 { # search in default linker directories
18996 # and then in all system paths
18997 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018998 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018999 }
19000 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019001 if(not defined $Cache{"checkSystemFiles"}) {
19002 checkSystemFiles();
19003 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019004 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19005 return $AllObjects[0];
19006 }
19007 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19008 {
19009 if($ShortName ne $Name)
19010 { # FIXME: check this case
19011 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19012 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019013 }
19014 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019015 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019016 # can't find
19017 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019018}
19019
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019020sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019021{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019022 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19023 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019024
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019025 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019026
19027 if(not $Real_Path)
19028 { # broken link
19029 return ();
19030 }
19031
19032 my $Lib_Name = get_filename($Real_Path);
19033
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019034 if($ExtraInfo)
19035 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019036 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019037 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019038 }
19039
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019040 if($IsNeededLib)
19041 {
19042 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19043 return ();
19044 }
19045 }
19046 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019047 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019048
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019049 push(@RecurLib, $Lib_Name);
19050 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019051 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19052
19053 if(not $IsNeededLib)
19054 { # special cases: libstdc++ and libc
19055 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19056 {
19057 if($ShortName eq "libstdc++")
19058 { # libstdc++.so.6
19059 $STDCXX_TESTING = 1;
19060 }
19061 elsif($ShortName eq "libc")
19062 { # libc-2.11.3.so
19063 $GLIBC_TESTING = 1;
19064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019065 }
19066 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019067 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019068 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019069 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019070 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019071 mkpath(get_dirname($DebugPath));
19072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019073 if($OStarget eq "macos")
19074 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019075 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019076 if(not $NM) {
19077 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019078 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019079 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019080 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019081 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019082 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019083 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019084 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019085 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019086 else
19087 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019088 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019090 while(<LIB>)
19091 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019092 if($CheckUndefined)
19093 {
19094 if(not $IsNeededLib)
19095 {
19096 if(/ U _([\w\$]+)\s*\Z/)
19097 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019098 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019099 next;
19100 }
19101 }
19102 }
19103
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019104 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019105 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019106 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019107 if($IsNeededLib)
19108 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019109 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019110 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019111 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19112 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019114 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019115 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019116 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019117 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19118 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019119 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19120 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019121 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019122 setLanguage($LibVersion, "C++");
19123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019125 }
19126 }
19127 }
19128 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019129
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019130 if($Deps)
19131 {
19132 if($LIB_TYPE eq "dynamic")
19133 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019134
19135 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019136 if(not $OtoolCmd) {
19137 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019138 }
19139
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019140 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19141 while(<LIB>)
19142 {
19143 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19144 and $1 ne $Lib_Path) {
19145 $NeededLib{$1} = 1;
19146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019147 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019148 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019150 }
19151 }
19152 elsif($OStarget eq "windows")
19153 { # Windows *.dll, *.lib
19154 my $DumpBinCmd = get_CmdPath("dumpbin");
19155 if(not $DumpBinCmd) {
19156 exitStatus("Not_Found", "can't find \"dumpbin\"");
19157 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019158 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019159 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019160 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019161 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019162 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019163 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019164 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019165 else
19166 { # write to pipe
19167 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019170 {
19171 my $realname = undef;
19172 if($LIB_TYPE eq "dynamic")
19173 {
19174 # 1197 4AC 0000A620 SetThreadStackGuarantee
19175 # 1198 4AD SetThreadToken (forwarded to ...)
19176 # 3368 _o2i_ECPublicKey
19177 # 1 0 00005B30 ??0?N = ... (with pdb)
19178 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19179 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19180 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19181 { # dynamic, static and forwarded symbols
19182 $realname = $1;
19183 }
19184 }
19185 else
19186 { # static
19187 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19188 {
19189 # 16 IID_ISecurityInformation
19190 $realname = $1;
19191 }
19192 }
19193
19194 if($realname)
19195 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019196 if($IsNeededLib)
19197 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019198 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019199 {
19200 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19201 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019203 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019204 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019205 {
19206 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19207 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019208 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19209 {
19210 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19211 setLanguage($LibVersion, "C++");
19212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214 }
19215 }
19216 }
19217 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019218
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019219 if($Deps)
19220 {
19221 if($LIB_TYPE eq "dynamic")
19222 { # dependencies
19223 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19224 while(<LIB>)
19225 {
19226 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19227 and $1 ne $Lib_Path) {
19228 $NeededLib{path_format($1, $OSgroup)} = 1;
19229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019230 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019231 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019233 }
19234 }
19235 else
19236 { # Unix; *.so, *.a
19237 # Symbian: *.dso, *.lib
19238 my $ReadelfCmd = get_CmdPath("readelf");
19239 if(not $ReadelfCmd) {
19240 exitStatus("Not_Found", "can't find \"readelf\"");
19241 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019242 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019243 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019244 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019245 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019246 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019247 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019248 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019249 else
19250 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019251 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019252 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019253 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 while(<LIB>)
19255 {
19256 if($LIB_TYPE eq "dynamic")
19257 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019258 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019259 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019260 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019261 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019262 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019263 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019264 # do nothing with symtab
19265 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019266 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019267 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019268 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019269 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019270 next;
19271 }
19272 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019273 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019274 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019275 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019276 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019277 if($CheckUndefined)
19278 {
19279 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019280 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019281 }
19282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019283 next;
19284 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019285 if($Bind eq "WEAK")
19286 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019287 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019288 if($Weak eq "-Weak")
19289 { # skip WEAK symbols
19290 next;
19291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019293 my $Short = $Symbol;
19294 $Short=~s/\@.+//g;
19295 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019296 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019297 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19298 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019300 if($IsNeededLib)
19301 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019302 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019303 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019304 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19305 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019307 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019308 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019309 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019310 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19311 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19312 if($Vers)
19313 {
19314 if($LIB_EXT eq "so")
19315 { # value
19316 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19317 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019319 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019320 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19321 {
19322 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19323 setLanguage($LibVersion, "C++");
19324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019326 }
19327 }
19328 }
19329 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019330
19331 if($Deps and $LIB_TYPE eq "dynamic")
19332 { # dynamic library specifics
19333 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19334 open(LIB, $Cmd." |");
19335
19336 while(<LIB>)
19337 {
19338 if(/NEEDED.+\[([^\[\]]+)\]/)
19339 { # dependencies:
19340 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19341 $NeededLib{$1} = 1;
19342 }
19343 }
19344
19345 close(LIB);
19346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019347 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019348 if($Vers)
19349 {
19350 if(not $IsNeededLib and $LIB_EXT eq "so")
19351 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019352 my %Found = ();
19353
19354 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019355 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019356 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019357 next if(index($Symbol,"\@")==-1);
19358 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019359 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019360 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019361 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019362 if($Symbol_SameValue ne $Symbol
19363 and index($Symbol_SameValue,"\@")==-1)
19364 {
19365 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019366 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019367 last;
19368 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019369 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019370 }
19371 }
19372
19373 # default
19374 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19375 {
19376 next if(defined $Found{$Symbol});
19377 next if(index($Symbol,"\@\@")==-1);
19378
19379 if($Symbol=~/\A([^\@]*)\@\@/
19380 and not $SymVer{$LibVersion}{$1})
19381 {
19382 $SymVer{$LibVersion}{$1} = $Symbol;
19383 $Found{$Symbol} = 1;
19384 }
19385 }
19386
19387 # non-default
19388 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19389 {
19390 next if(defined $Found{$Symbol});
19391 next if(index($Symbol,"\@")==-1);
19392
19393 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19394 and not $SymVer{$LibVersion}{$1})
19395 {
19396 $SymVer{$LibVersion}{$1} = $Symbol;
19397 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019398 }
19399 }
19400 }
19401 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019402 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019403 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019404 foreach my $DyLib (sort keys(%NeededLib))
19405 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019406 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19407
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019408 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19409 {
19410 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19411 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19412 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019414 }
19415 }
19416 pop(@RecurLib);
19417 return $Library_Symbol{$LibVersion};
19418}
19419
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019420sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019421{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019422 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019423 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019424 return keys(%Prefixes);
19425}
19426
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019427sub get_prefixes_I($$)
19428{
19429 foreach my $P (@{$_[0]})
19430 {
19431 my @Parts = reverse(split(/[\/\\]+/, $P));
19432 my $Name = $Parts[0];
19433 foreach (1 .. $#Parts)
19434 {
19435 $_[1]->{$Name}{$P} = 1;
19436 last if($_>4 or $Parts[$_] eq "include");
19437 $Name = $Parts[$_].$SLASH.$Name;
19438 }
19439 }
19440}
19441
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019442sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019443{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019444 $Cache{"checkSystemFiles"} = 1;
19445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019446 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019447
19448 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019449 {
19450 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019451
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019452 my @Files = cmd_find($DevelPath,"f");
19453 foreach my $Link (cmd_find($DevelPath,"l"))
19454 { # add symbolic links
19455 if(-f $Link) {
19456 push(@Files, $Link);
19457 }
19458 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019459
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019460 # search for headers in /usr/lib
19461 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19462 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19463 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019464
19465 # search for libraries in /usr/lib (including symbolic links)
19466 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19467 foreach my $Path (@Libs)
19468 {
19469 my $N = get_filename($Path);
19470 $SystemObjects{$N}{$Path} = 1;
19471 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019472 }
19473 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019474
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019475 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019476 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019477 next if(not -d $DevelPath);
19478 # search for all header files in the /usr/include
19479 # with or without extension (ncurses.h, QtCore, ...)
19480 push(@SysHeaders, cmd_find($DevelPath,"f"));
19481 foreach my $Link (cmd_find($DevelPath,"l"))
19482 { # add symbolic links
19483 if(-f $Link) {
19484 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019486 }
19487 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019488 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019489}
19490
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019491sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019492{
19493 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019494 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019495 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19496 {
19497 if(not -e $Dest) {
19498 exitStatus("Access_Error", "can't access \'$Dest\'");
19499 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019500 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019501 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19502 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019503 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019504 }
19505 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019506 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019507}
19508
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019509sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019510{
19511 my ($Path, $LibVersion) = @_;
19512 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019513 my $Name = get_filename($Path);
19514 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019515 return 1;
19516 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019517 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019518 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19519 return 1;
19520 }
19521 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19522 {
19523 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19524 return 1;
19525 }
19526 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019527 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019528 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019529 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019530 return 1;
19531 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019532 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019533 return 1;
19534 }
19535 }
19536 return 0;
19537}
19538
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019539sub specificHeader($$)
19540{
19541 my ($Header, $Spec) = @_;
19542 my $Name = get_filename($Header);
19543
19544 if($Spec eq "windows")
19545 {# MS Windows
19546 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19547 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19548 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19549 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19550 my @Dirs = (
19551 "win32",
19552 "win64",
19553 "win",
19554 "windows",
19555 "msvcrt"
19556 ); # /gsf-win32/
19557 if(my $DIRs = join("|", @Dirs)) {
19558 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19559 }
19560 }
19561 elsif($Spec eq "macos")
19562 { # Mac OS
19563 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19564 }
19565
19566 return 0;
19567}
19568
19569sub skipAlienHeader($)
19570{
19571 my $Path = $_[0];
19572 my $Name = get_filename($Path);
19573 my $Dir = get_dirname($Path);
19574
19575 if($Tolerance=~/2/)
19576 { # 2 - skip internal headers
19577 my @Terms = (
19578 "p",
19579 "priv",
19580 "int",
19581 "impl",
19582 "implementation",
19583 "internal",
19584 "private",
19585 "old",
19586 "compat",
19587 "debug",
19588 "test",
19589 "gen"
19590 );
19591
19592 my @Dirs = (
19593 "private",
19594 "priv",
19595 "port",
19596 "impl",
19597 "internal",
19598 "detail",
19599 "details",
19600 "old",
19601 "compat",
19602 "debug",
19603 "config",
19604 "compiler",
19605 "platform",
19606 "test"
19607 );
19608
19609 if(my $TERMs = join("|", @Terms)) {
19610 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19611 }
19612 if(my $DIRs = join("|", @Dirs)) {
19613 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19614 }
19615
19616 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19617 }
19618
19619 if($Tolerance=~/1/)
19620 { # 1 - skip non-Linux headers
19621 if($OSgroup ne "windows")
19622 {
19623 if(specificHeader($Path, "windows")) {
19624 return 1;
19625 }
19626 }
19627 if($OSgroup ne "macos")
19628 {
19629 if(specificHeader($Path, "macos")) {
19630 return 1;
19631 }
19632 }
19633 }
19634
19635 # valid
19636 return 0;
19637}
19638
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019639sub skipHeader($$)
19640{
19641 my ($Path, $LibVersion) = @_;
19642 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019643 if(defined $Cache{"skipHeader"}{$Path}) {
19644 return $Cache{"skipHeader"}{$Path};
19645 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019646 if(defined $Tolerance and $Tolerance=~/1|2/)
19647 { # --tolerant
19648 if(skipAlienHeader($Path)) {
19649 return ($Cache{"skipHeader"}{$Path} = 1);
19650 }
19651 }
19652 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19653 return 0;
19654 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019655 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19656}
19657
19658sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659{ # returns:
19660 # 1 - if header should NOT be included and checked
19661 # 2 - if header should NOT be included, but should be checked
19662 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019663 my $Name = get_filename($Path);
19664 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019665 return $Kind;
19666 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019667 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19668 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019669 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019670 if(index($Path, $D)!=-1)
19671 {
19672 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19673 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019675 }
19676 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019677 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19678 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019679 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019680 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19681 {
19682 if($Name=~/$P/) {
19683 return $Kind;
19684 }
19685 if($P=~/[\/\\]/ and $Path=~/$P/) {
19686 return $Kind;
19687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019688 }
19689 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019691 return 0;
19692}
19693
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019694sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019695{
19696 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019697 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019698 { # system directory
19699 return;
19700 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019701 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019702 { # already registered
19703 return;
19704 }
19705 foreach my $Path (find_libs($Dir,"",1))
19706 {
19707 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019708 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019709 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019710 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019711 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19712}
19713
19714sub registerObject($$)
19715{
19716 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019717
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019718 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019719 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019720 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019721 {
19722 if(my $SONAME = getSONAME($Path)) {
19723 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19724 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019725 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019726 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19727 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019728 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019729
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019730 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019731 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019732 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019733 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019734 if($ObjArch ne getArch_GCC($LibVersion))
19735 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19736 $CheckedArch{$LibVersion} = 1;
19737 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 +040019738 }
19739 }
19740 }
19741}
19742
19743sub getArch_Object($)
19744{
19745 my $Path = $_[0];
19746
19747 my %MachineType = (
19748 "14C" => "x86",
19749 "8664" => "x86_64",
19750 "1C0" => "arm",
19751 "200" => "ia64"
19752 );
19753
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019754 my %ArchName = (
19755 "s390:31-bit" => "s390",
19756 "s390:64-bit" => "s390x",
19757 "powerpc:common" => "ppc32",
19758 "powerpc:common64" => "ppc64",
19759 "i386:x86-64" => "x86_64",
19760 "mips:3000" => "mips",
19761 "sparc:v8plus" => "sparcv9"
19762 );
19763
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019764 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019765 {
19766 my $DumpbinCmd = get_CmdPath("dumpbin");
19767 if(not $DumpbinCmd) {
19768 exitStatus("Not_Found", "can't find \"dumpbin\"");
19769 }
19770
19771 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19772 my $Out = `$Cmd`;
19773
19774 if($Out=~/(\w+)\smachine/)
19775 {
19776 if(my $Type = $MachineType{uc($1)})
19777 {
19778 return $Type;
19779 }
19780 }
19781 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019782 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019783 {
19784 my $ObjdumpCmd = get_CmdPath("objdump");
19785 if(not $ObjdumpCmd) {
19786 exitStatus("Not_Found", "can't find \"objdump\"");
19787 }
19788
19789 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019790
19791 if($OSgroup eq "windows") {
19792 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19793 }
19794 else {
19795 $Cmd = "LANG=$LOCALE ".$Cmd;
19796 }
19797 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019798
19799 if($Out=~/architecture:\s+([\w\-\:]+)/)
19800 {
19801 my $Arch = $1;
19802 if($Arch=~s/\:(.+)//)
19803 {
19804 my $Suffix = $1;
19805
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019806 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019807 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019808 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019809 }
19810 }
19811
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019812 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019813 $Arch = "x86";
19814 }
19815
19816 if($Arch eq "x86-64") {
19817 $Arch = "x86_64";
19818 }
19819
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019820 if($Arch eq "ia64-elf64") {
19821 $Arch = "ia64";
19822 }
19823
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019824 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019825 }
19826 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019827 elsif($OStarget=~/macos/)
19828 {
19829 my $OtoolCmd = get_CmdPath("otool");
19830 if(not $OtoolCmd) {
19831 exitStatus("Not_Found", "can't find \"otool\"");
19832 }
19833
19834 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19835 my $Out = qx/$Cmd/;
19836
19837 if($Out=~/X86_64/i) {
19838 return "x86_64";
19839 }
19840 elsif($Out=~/X86/i) {
19841 return "x86";
19842 }
19843 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019844 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019845 {
19846 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019847 # TODO
19848 }
19849
19850 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019851}
19852
19853sub getSONAME($)
19854{
19855 my $Path = $_[0];
19856 return if(not $Path);
19857 if(defined $Cache{"getSONAME"}{$Path}) {
19858 return $Cache{"getSONAME"}{$Path};
19859 }
19860 my $ObjdumpCmd = get_CmdPath("objdump");
19861 if(not $ObjdumpCmd) {
19862 exitStatus("Not_Found", "can't find \"objdump\"");
19863 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019864 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019865 if($OSgroup eq "windows") {
19866 $SonameCmd .= " | find \"SONAME\"";
19867 }
19868 else {
19869 $SonameCmd .= " | grep SONAME";
19870 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019871 if(my $SonameInfo = `$SonameCmd`)
19872 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019873 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19874 return ($Cache{"getSONAME"}{$Path} = $1);
19875 }
19876 }
19877 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019878}
19879
19880sub getSOPaths_Dest($$)
19881{
19882 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019883 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019884 return ();
19885 }
19886 if(-f $Dest)
19887 {
19888 if(not parse_libname($Dest, "name", $OStarget)) {
19889 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19890 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019891 registerObject($Dest, $LibVersion);
19892 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019893 return ($Dest);
19894 }
19895 elsif(-d $Dest)
19896 {
19897 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019898 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019899 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019900 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19901 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019902 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019903 { # all files and symlinks that match the name of a library
19904 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19905 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019906 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019907 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019908 }
19909 }
19910 }
19911 else
19912 { # search for all files and symlinks
19913 foreach my $Path (find_libs($Dest,"",""))
19914 {
19915 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019916 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019917 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019918 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019919 }
19920 if($OSgroup eq "macos")
19921 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019922 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019923 {
19924 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019925 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019926 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019927 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19928 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019929 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019930 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019931 }
19932 }
19933 }
19934 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019935 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019936 }
19937 else {
19938 return ();
19939 }
19940}
19941
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019942sub realpath_F($)
19943{
19944 my $Path = $_[0];
19945 return path_format(realpath($Path), $OSgroup);
19946}
19947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019948sub isCyclical($$)
19949{
19950 my ($Stack, $Value) = @_;
19951 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019952}
19953
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019954sub getGCC_Opts($)
19955{ # to use in module
19956 my $LibVersion = $_[0];
19957
19958 my @Opts = ();
19959
19960 if($CompilerOptions{$LibVersion})
19961 { # user-defined options
19962 push(@Opts, $CompilerOptions{$LibVersion});
19963 }
19964 if($GccOptions)
19965 { # additional
19966 push(@Opts, $GccOptions);
19967 }
19968
19969 if(@Opts) {
19970 return join(" ", @Opts);
19971 }
19972
19973 return undef;
19974}
19975
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019976sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019977{
19978 my $LibVersion = $_[0];
19979
19980 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19981 return $Cache{"getArch_GCC"}{$LibVersion};
19982 }
19983
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019984 if(not $GCC_PATH) {
19985 return undef;
19986 }
19987
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019988 my $Arch = undef;
19989
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019990 if(my $Target = get_dumpmachine($GCC_PATH))
19991 {
19992 if($Target=~/x86_64/) {
19993 $Arch = "x86_64";
19994 }
19995 elsif($Target=~/i[3-6]86/) {
19996 $Arch = "x86";
19997 }
19998 elsif($Target=~/\Aarm/i) {
19999 $Arch = "arm";
20000 }
20001 }
20002
20003 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020004 {
20005 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20006
20007 my $Cmd = $GCC_PATH." test.c -o test";
20008 if(my $Opts = getGCC_Opts($LibVersion))
20009 { # user-defined options
20010 $Cmd .= " ".$Opts;
20011 }
20012
20013 chdir($TMP_DIR);
20014 system($Cmd);
20015 chdir($ORIG_DIR);
20016
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020017 my $EX = join_P($TMP_DIR, "test");
20018
20019 if($OSgroup eq "windows") {
20020 $EX = join_P($TMP_DIR, "test.exe");
20021 }
20022
20023 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020024
20025 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020026 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020027 }
20028
20029 if(not $Arch) {
20030 exitStatus("Error", "can't check ARCH type");
20031 }
20032
20033 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20034}
20035
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020036sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020037{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020038 my $LibVersion = $_[0];
20039
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020040 my $Size = undef;
20041
20042 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020043 if(my $Arch = getArch($LibVersion))
20044 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020045 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020046 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020047 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020048 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20049 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020050 }
20051 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020052
20053 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020054 {
20055 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020056
20057 my $Cmd = $GCC_PATH." -E -dD empty.h";
20058 if(my $Opts = getGCC_Opts($LibVersion))
20059 { # user-defined options
20060 $Cmd .= " ".$Opts;
20061 }
20062
20063 chdir($TMP_DIR);
20064 my $Defines = `$Cmd`;
20065 chdir($ORIG_DIR);
20066
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020067 unlink("$TMP_DIR/empty.h");
20068
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020069 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20070 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020071 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020072 }
20073 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20074 { # GCC 3
20075 my $PTRDIFF = $1;
20076 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020077 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020078 }
20079 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020080 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020081 }
20082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020084
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020085 if(not $Size) {
20086 exitStatus("Error", "can't check WORD size");
20087 }
20088
20089 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020090}
20091
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020092sub getWordSize($)
20093{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020094 return $WORD_SIZE{$_[0]};
20095}
20096
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020097sub majorVersion($)
20098{
20099 my $V = $_[0];
20100 return 0 if(not $V);
20101 my @VParts = split(/\./, $V);
20102 return $VParts[0];
20103}
20104
20105sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020106{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020107 my ($V1, $V2) = @_;
20108 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020109 my @V1Parts = split(/\./, $V1);
20110 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020111 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20112 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20114 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20115 }
20116 return -1 if($#V1Parts < $#V2Parts);
20117 return 1 if($#V1Parts > $#V2Parts);
20118 return 0;
20119}
20120
20121sub read_ABI_Dump($$)
20122{
20123 my ($LibVersion, $Path) = @_;
20124 return if(not $LibVersion or not -e $Path);
20125 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020126 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020127 { # input *.abi
20128 $FilePath = $Path;
20129 }
20130 else
20131 { # input *.abi.tar.gz
20132 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020133 if(not isDump_U($FilePath)) {
20134 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020136 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020137
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020138 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020139
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020140 my $Line = readLineNum($FilePath, 0);
20141 if($Line=~/xml/)
20142 { # XML format
20143 loadModule("XmlDump");
20144 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020145 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020146 else
20147 { # Perl Data::Dumper format (default)
20148 open(DUMP, $FilePath);
20149 local $/ = undef;
20150 my $Content = <DUMP>;
20151 close(DUMP);
20152
20153 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20154 { # remove temp file
20155 unlink($FilePath);
20156 }
20157 if($Content!~/};\s*\Z/) {
20158 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20159 }
20160 $ABI = eval($Content);
20161 if(not $ABI) {
20162 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020164 }
20165 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020166 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020167 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020168 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020169 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020170 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020171 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020172 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020173 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020174
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020175 if($ABI->{"PublicABI"}) {
20176 $UsedDump{$LibVersion}{"Public"} = 1;
20177 }
20178
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020179 if($ABI->{"ABI_DUMP_VERSION"})
20180 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020181 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020182 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020183 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020184 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020185 }
20186 else
20187 { # support for old ABI dumps
20188 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020189 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020190 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020191 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020192 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020193
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020194 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020195 {
20196 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 +040020197 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020198
20199 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20200 { # DWARF ABI Dump
20201 $UseConv_Real{$LibVersion}{"P"} = 1;
20202 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20203
20204 $UsedDump{$LibVersion}{"DWARF"} = 1;
20205
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020206 if(not $TargetComponent_Opt)
20207 {
20208 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20209 $TargetComponent = "module";
20210 }
20211 else {
20212 $TargetComponent = "object";
20213 }
20214 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020215 }
20216
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020217 if(not checkDump($LibVersion, "2.11"))
20218 { # old ABI dumps
20219 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020220 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020221 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020222 { # ABI dump created with --binary option
20223 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20224 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020225 else
20226 { # default
20227 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20228 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020229
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020230 if(defined $ABI->{"Mode"}
20231 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020232 { # --ext option
20233 $ExtendedCheck = 1;
20234 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020235 if($ABI->{"Extra"}) {
20236 $ExtraDump = 1;
20237 }
20238
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020239 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020240 {
20241 $UsedDump{$LibVersion}{"L"} = $Lang;
20242 setLanguage($LibVersion, $Lang);
20243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020244 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020245 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020246 }
20247 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020248 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020249 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020250 if(not $TInfo)
20251 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020252 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020253 }
20254 my %Tid_TDid = ();
20255 foreach my $TDid (keys(%{$TInfo}))
20256 {
20257 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20258 {
20259 $MAX_ID = $Tid if($Tid>$MAX_ID);
20260 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020261 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020262 }
20263 }
20264 my %NewID = ();
20265 foreach my $Tid (keys(%Tid_TDid))
20266 {
20267 my @TDids = keys(%{$Tid_TDid{$Tid}});
20268 if($#TDids>=1)
20269 {
20270 foreach my $TDid (@TDids)
20271 {
20272 if($TDid) {
20273 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20274 }
20275 else
20276 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020277 my $ID = ++$MAX_ID;
20278
20279 $NewID{$TDid}{$Tid} = $ID;
20280 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20281 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020282 }
20283 }
20284 }
20285 else
20286 {
20287 my $TDid = $TDids[0];
20288 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20289 }
20290 }
20291 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20292 {
20293 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20294 if(defined $Info{"BaseType"})
20295 {
20296 my $Bid = $Info{"BaseType"}{"Tid"};
20297 my $BDid = $Info{"BaseType"}{"TDid"};
20298 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020299 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020300 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20301 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020303 }
20304 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020306 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020307 read_Machine_DumpInfo($ABI, $LibVersion);
20308 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020309 if(not $SymbolInfo{$LibVersion})
20310 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020311 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020312 }
20313 if(not keys(%{$SymbolInfo{$LibVersion}}))
20314 { # validation of old-version dumps
20315 if(not $ExtendedCheck) {
20316 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20317 }
20318 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020319 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020320 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020321 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020322 else
20323 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020324 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020325 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020326 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020327 }
20328 if(not $DepSymbols)
20329 { # Cannot reconstruct DepSymbols. This may result in false
20330 # positives if the old dump is for library 2. Not a problem if
20331 # old dumps are only from old libraries.
20332 $DepSymbols = {};
20333 }
20334 foreach my $Symbol (keys(%{$DepSymbols})) {
20335 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020337 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020338 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020339
20340 if(my $V = $TargetVersion{$LibVersion}) {
20341 $Descriptor{$LibVersion}{"Version"} = $V;
20342 }
20343 else {
20344 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20345 }
20346
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020347 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020348 { # if not defined by -skip-types option
20349 if(defined $ABI->{"SkipTypes"})
20350 {
20351 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20352 {
20353 $SkipTypes{$LibVersion}{$TName} = 1;
20354 }
20355 }
20356 if(defined $ABI->{"OpaqueTypes"})
20357 { # support for old dumps
20358 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20359 {
20360 $SkipTypes{$LibVersion}{$TName} = 1;
20361 }
20362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020363 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020364
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020365 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020366 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020367 if(defined $ABI->{"SkipSymbols"}) {
20368 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20369 }
20370 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020371 { # support for old dumps
20372 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20373 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020374 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020375 { # support for old dumps
20376 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020378 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020379 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020380
20381 if(not $TargetHeaders{$LibVersion})
20382 { # if not defined by -headers-list option
20383 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20384 }
20385
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020386 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020388 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020389
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020390 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020391 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020392 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020393
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020394 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020395 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020396
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020397 if(not checkDump($LibVersion, "2.10.1")
20398 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020399 { # support for old ABI dumps: added target headers
20400 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020401 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020402 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020403
20404 if(not $ABI->{"PublicABI"})
20405 {
20406 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20407 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020409 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020410 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020411 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020412 if(defined $ABI->{"GccConstants"})
20413 { # 3.0
20414 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20415 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20416 }
20417 }
20418
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020419 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020420 if(not $NestedNameSpaces{$LibVersion})
20421 { # support for old dumps
20422 # Cannot reconstruct NameSpaces. This may affect design
20423 # of the compatibility report.
20424 $NestedNameSpaces{$LibVersion} = {};
20425 }
20426 # target system type
20427 # needed to adopt HTML report
20428 if(not $DumpSystem)
20429 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020430 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020431 }
20432 # recreate environment
20433 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20434 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020435 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020436 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020437 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20438 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020439 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020440 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020441 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020442 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20443 {
20444 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20445 setLanguage($LibVersion, "C++");
20446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020447 }
20448 }
20449 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020450 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20451 {
20452 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20453 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20454 }
20455 }
20456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020457 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020458 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020459 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020460 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020461 {
20462 if(not $Symbol_Library{$LibVersion}{$MnglName}
20463 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20464 push(@VFunc, $MnglName);
20465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 }
20467 }
20468 translateSymbols(@VFunc, $LibVersion);
20469 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020470 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20471
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020472 if(not checkDump($LibVersion, "3.0"))
20473 { # support for old ABI dumps
20474 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20475 {
20476 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20477 {
20478 if(ref($BaseType) eq "HASH") {
20479 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20480 }
20481 }
20482 }
20483 }
20484
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020485 if(not checkDump($LibVersion, "3.2"))
20486 { # support for old ABI dumps
20487 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20488 {
20489 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20490 {
20491 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20492 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20493 }
20494 }
20495 }
20496
20497 # repair target headers list
20498 delete($TargetHeaders{$LibVersion});
20499 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020500 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20501 }
20502 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20503 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020504 }
20505
20506 # non-target constants from anon enums
20507 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20508 {
20509 if(not $ExtraDump
20510 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20511 {
20512 delete($Constants{$LibVersion}{$Name});
20513 }
20514 }
20515 }
20516
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020517 if(not checkDump($LibVersion, "2.20"))
20518 { # support for old ABI dumps
20519 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20520 {
20521 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20522
20523 if($TType=~/Struct|Union|Enum|Typedef/)
20524 { # repair complex types first
20525 next;
20526 }
20527
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020528 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020529 {
20530 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20531 if($BType=~/Struct|Union|Enum/i)
20532 {
20533 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20534 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20535 }
20536 }
20537 }
20538 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20539 {
20540 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20541 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20542 if($TType=~/Struct|Union|Enum/) {
20543 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20544 }
20545 }
20546 }
20547
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020548 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020549 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020550 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20551 { # support for old ABI dumps < 2.0 (ACC 1.22)
20552 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20553 {
20554 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20555 {
20556 if($Access ne "public") {
20557 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20558 }
20559 }
20560 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20561 }
20562 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20563 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020564 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20565 { # support for old ABI dumps
20566 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20567 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020568 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20569 { # DWARF ABI Dumps
20570 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20571 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020572 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20573 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20574 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020575
20576 # support for old formatting of type names
20577 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20578
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020579 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20580 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020581 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020582 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20583 {
20584 if($SubId eq $TypeId)
20585 { # Fix erroneus ABI dump
20586 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20587 next;
20588 }
20589
20590 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020592 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020593 if($TInfo{"Type"} eq "MethodPtr")
20594 {
20595 if(defined $TInfo{"Param"})
20596 { # support for old ABI dumps <= 1.17
20597 if(not defined $TInfo{"Param"}{"0"})
20598 {
20599 my $Max = keys(%{$TInfo{"Param"}});
20600 foreach my $Pos (1 .. $Max) {
20601 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20602 }
20603 delete($TInfo{"Param"}{$Max});
20604 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20605 }
20606 }
20607 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020608 if($TInfo{"BaseType"} eq $TypeId)
20609 { # fix ABI dump
20610 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20611 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020612
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020613 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020614 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020615 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020617 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20618 if(not $BName)
20619 { # broken type
20620 next;
20621 }
20622 if($TInfo{"Name"} eq $BName)
20623 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020624 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020625 next;
20626 }
20627 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20628 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020629 }
20630 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020631 }
20632 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20633 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020634 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020635 }
20636 }
20637
20638 if(not checkDump($LibVersion, "2.15"))
20639 { # support for old ABI dumps
20640 my %Dups = ();
20641 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20642 {
20643 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020644 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020645 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20646 { # remove template decls
20647 delete($SymbolInfo{$LibVersion}{$InfoId});
20648 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020650 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020651 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20652 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020653 { # templates
20654 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020655 }
20656 }
20657 }
20658
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020659 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20660 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020661 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20662 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20663 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20664 { # support for old ABI dumps (< 3.1)
20665 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20666 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20667 { # add "this" first parameter
20668 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20669 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20670
20671 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20672 {
20673 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20674 foreach my $Pos (reverse(0 .. $#Pos)) {
20675 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20676 }
20677 }
20678 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20679 }
20680 }
20681
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020682 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20683 { # ABI dumps have no mangled names for C-functions
20684 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20685 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020686 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20687 { # support for old ABI dumps
20688 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20689 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020690 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20691 { # DWARF ABI Dumps
20692 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20693 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020694 }
20695
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020696 $Descriptor{$LibVersion}{"Dump"} = 1;
20697}
20698
20699sub read_Machine_DumpInfo($$)
20700{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020701 my ($ABI, $LibVersion) = @_;
20702 if($ABI->{"Arch"}) {
20703 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020705 if($ABI->{"WordSize"}) {
20706 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020707 }
20708 else
20709 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020710 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 }
20712 if(not $WORD_SIZE{$LibVersion})
20713 { # support for old dumps (<1.23)
20714 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20715 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020716 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020717 }
20718 else
20719 {
20720 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020721 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020722 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020723 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20724 { # any "pointer"-type
20725 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020726 last;
20727 }
20728 }
20729 if($PSize)
20730 { # a pointer type size
20731 $WORD_SIZE{$LibVersion} = $PSize;
20732 }
20733 else {
20734 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20735 }
20736 }
20737 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020738 if($ABI->{"GccVersion"}) {
20739 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020740 }
20741}
20742
20743sub read_Libs_DumpInfo($$)
20744{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020745 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020746 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20747 if(not $Library_Symbol{$LibVersion})
20748 { # support for old dumps
20749 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020751 if(keys(%{$Library_Symbol{$LibVersion}})
20752 and not $DumpAPI) {
20753 $Descriptor{$LibVersion}{"Libs"} = "OK";
20754 }
20755}
20756
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020757sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020759 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020760
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020761 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020762 and not $DumpAPI) {
20763 $Descriptor{$LibVersion}{"Headers"} = "OK";
20764 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020765 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020766 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020767 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020768 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020769 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020770
20771 if(keys(%{$ABI->{"Sources"}})
20772 and not $DumpAPI) {
20773 $Descriptor{$LibVersion}{"Sources"} = "OK";
20774 }
20775 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020776 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020777 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20778 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780}
20781
20782sub find_libs($$$)
20783{
20784 my ($Path, $Type, $MaxDepth) = @_;
20785 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020786 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787}
20788
20789sub createDescriptor($$)
20790{
20791 my ($LibVersion, $Path) = @_;
20792 if(not $LibVersion or not $Path
20793 or not -e $Path) {
20794 return "";
20795 }
20796 if(-d $Path)
20797 { # directory with headers files and shared objects
20798 return "
20799 <version>
20800 ".$TargetVersion{$LibVersion}."
20801 </version>
20802
20803 <headers>
20804 $Path
20805 </headers>
20806
20807 <libs>
20808 $Path
20809 </libs>";
20810 }
20811 else
20812 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020813 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020814 { # standard XML-descriptor
20815 return readFile($Path);
20816 }
20817 elsif(is_header($Path, 2, $LibVersion))
20818 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020819 $CheckHeadersOnly = 1;
20820
20821 if($LibVersion==1) {
20822 $TargetVersion{$LibVersion} = "X";
20823 }
20824
20825 if($LibVersion==2) {
20826 $TargetVersion{$LibVersion} = "Y";
20827 }
20828
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020829 return "
20830 <version>
20831 ".$TargetVersion{$LibVersion}."
20832 </version>
20833
20834 <headers>
20835 $Path
20836 </headers>
20837
20838 <libs>
20839 none
20840 </libs>";
20841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020842 else
20843 { # standard XML-descriptor
20844 return readFile($Path);
20845 }
20846 }
20847}
20848
20849sub detect_lib_default_paths()
20850{
20851 my %LPaths = ();
20852 if($OSgroup eq "bsd")
20853 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020854 if(my $LdConfig = get_CmdPath("ldconfig"))
20855 {
20856 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20857 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020858 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20859 {
20860 my $Name = "lib".$1;
20861 if(not defined $LPaths{$Name}) {
20862 $LPaths{$Name} = $2;
20863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020864 }
20865 }
20866 }
20867 else {
20868 printMsg("WARNING", "can't find ldconfig");
20869 }
20870 }
20871 else
20872 {
20873 if(my $LdConfig = get_CmdPath("ldconfig"))
20874 {
20875 if($SystemRoot and $OSgroup eq "linux")
20876 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20877 if(-e $SystemRoot."/etc/ld.so.conf") {
20878 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20879 }
20880 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020881 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20882 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20884 {
20885 my ($Name, $Path) = ($1, $2);
20886 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020887 if(not defined $LPaths{$Name})
20888 { # get first element from the list of available paths
20889
20890 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20891 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20892 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20893
20894 $LPaths{$Name} = $Path;
20895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020896 }
20897 }
20898 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020899 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900 printMsg("WARNING", "can't find ldconfig");
20901 }
20902 }
20903 return \%LPaths;
20904}
20905
20906sub detect_bin_default_paths()
20907{
20908 my $EnvPaths = $ENV{"PATH"};
20909 if($OSgroup eq "beos") {
20910 $EnvPaths.=":".$ENV{"BETOOLS"};
20911 }
20912 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020913 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020914 {
20915 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020916 next if(not $Path);
20917 if($SystemRoot
20918 and $Path=~/\A\Q$SystemRoot\E\//)
20919 { # do NOT use binaries from target system
20920 next;
20921 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020922 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020923 }
20924}
20925
20926sub detect_inc_default_paths()
20927{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020928 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020929 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020930 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020931 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020932 next if(index($Line, "/cc1plus ")!=-1);
20933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020934 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20935 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020936 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020937 if(index($Path, "c++")!=-1
20938 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020939 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020940 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020941 if(not defined $MAIN_CPP_DIR
20942 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20943 $MAIN_CPP_DIR = $Path;
20944 }
20945 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020946 elsif(index($Path, "gcc")!=-1) {
20947 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020948 }
20949 else
20950 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020951 if($Path=~/local[\/\\]+include/)
20952 { # local paths
20953 next;
20954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 if($SystemRoot
20956 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20957 { # The GCC include path for user headers is not a part of the system root
20958 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20959 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20960 next;
20961 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020962 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020963 }
20964 }
20965 }
20966 unlink("$TMP_DIR/empty.h");
20967 return %DPaths;
20968}
20969
20970sub detect_default_paths($)
20971{
20972 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20973 my $Search = $_[0];
20974 if($Search!~/inc/) {
20975 $HSearch = 0;
20976 }
20977 if($Search!~/lib/) {
20978 $LSearch = 0;
20979 }
20980 if($Search!~/bin/) {
20981 $BSearch = 0;
20982 }
20983 if($Search!~/gcc/) {
20984 $GSearch = 0;
20985 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020986 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987 { # <search_headers> section of the XML descriptor
20988 # do NOT search for systems headers
20989 $HSearch = 0;
20990 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020991 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020992 { # <search_libs> section of the XML descriptor
20993 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020994 $LSearch = 0;
20995 }
20996 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20997 { # additional search paths
20998 next if($Type eq "include" and not $HSearch);
20999 next if($Type eq "lib" and not $LSearch);
21000 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021001 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021002 }
21003 if($OSgroup ne "windows")
21004 { # unix-like
21005 foreach my $Type ("include", "lib", "bin")
21006 { # automatic detection of system "devel" directories
21007 next if($Type eq "include" and not $HSearch);
21008 next if($Type eq "lib" and not $LSearch);
21009 next if($Type eq "bin" and not $BSearch);
21010 my ($UsrDir, $RootDir) = ("/usr", "/");
21011 if($SystemRoot and $Type ne "bin")
21012 { # 1. search for target headers and libraries
21013 # 2. use host commands: ldconfig, readelf, etc.
21014 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21015 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021016 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021017 if(-d $RootDir."/".$Type)
21018 { # if "/lib" is symbolic link
21019 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021020 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021 }
21022 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021023 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021024 }
21025 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021026 if(-d $UsrDir)
21027 {
21028 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021029 if(-d $UsrDir."/".$Type)
21030 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021031 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021032 }
21033 }
21034 }
21035 }
21036 if($BSearch)
21037 {
21038 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021039 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021040 }
21041 # check environment variables
21042 if($OSgroup eq "beos")
21043 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021044 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021045 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021046 if($_ eq ".") {
21047 next;
21048 }
21049 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21050 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21051 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021052 }
21053 }
21054 if($HSearch)
21055 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021056 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21057 split(/:|;/, $ENV{"BEINCLUDES"})
21058 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021059 }
21060 if($LSearch)
21061 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021062 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21063 split(/:|;/, $ENV{"BELIBRARIES"}),
21064 split(/:|;/, $ENV{"LIBRARY_PATH"})
21065 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021066 }
21067 }
21068 if($LSearch)
21069 { # using linker to get system paths
21070 if(my $LPaths = detect_lib_default_paths())
21071 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021072 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021073 foreach my $Name (keys(%{$LPaths}))
21074 {
21075 if($SystemRoot
21076 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21077 { # wrong ldconfig configuration
21078 # check your <sysroot>/etc/ld.so.conf
21079 next;
21080 }
21081 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021082 if(my $Dir = get_dirname($LPaths->{$Name})) {
21083 $Dirs{$Dir} = 1;
21084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021085 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021086 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021087 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021088 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089 }
21090 if($BSearch)
21091 {
21092 if($CrossGcc)
21093 { # --cross-gcc=arm-linux-gcc
21094 if(-e $CrossGcc)
21095 { # absolute or relative path
21096 $GCC_PATH = get_abs_path($CrossGcc);
21097 }
21098 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21099 { # command name
21100 $GCC_PATH = $CrossGcc;
21101 }
21102 else {
21103 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21104 }
21105 if($GCC_PATH=~/\s/) {
21106 $GCC_PATH = "\"".$GCC_PATH."\"";
21107 }
21108 }
21109 }
21110 if($GSearch)
21111 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021112 if(not $CrossGcc)
21113 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021114 $GCC_PATH = get_CmdPath("gcc");
21115 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021116 if(not $GCC_PATH)
21117 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021118 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021119 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021120 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021121 { # select the latest version
21122 @GCCs = sort {$b cmp $a} @GCCs;
21123 if(check_gcc($GCCs[0], "3"))
21124 {
21125 $GCC_PATH = $GCCs[0];
21126 last;
21127 }
21128 }
21129 }
21130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021131 if(not $GCC_PATH) {
21132 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21133 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021134
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021135 my $GCC_Ver = get_dumpversion($GCC_PATH);
21136 if($GCC_Ver eq "4.8")
21137 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21138 my $Info = `$GCC_PATH --version`;
21139
21140 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21141 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21142 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21143 $GCC_Ver = $2;
21144 }
21145 }
21146
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021147 if($OStarget=~/macos/)
21148 {
21149 my $Info = `$GCC_PATH --version`;
21150
21151 if($Info=~/clang/i) {
21152 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21153 }
21154 }
21155
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021156 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021158 my $GccTarget = get_dumpmachine($GCC_PATH);
21159
21160 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021162 $OStarget = "linux";
21163 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021165 elsif($GccTarget=~/symbian/)
21166 {
21167 $OStarget = "symbian";
21168 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21169 }
21170
21171 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21172
21173 # check GCC version
21174 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21175 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021176 # introduced in 4.8 and fixed in 4.8.3
21177 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.");
21178
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021179 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021180 }
21181 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021182 else {
21183 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021184 }
21185 }
21186 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021187 {
21188 # GCC standard paths
21189 if($GCC_PATH and not $NoStdInc)
21190 {
21191 my %DPaths = detect_inc_default_paths();
21192 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21193 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21194 @DefaultIncPaths = @{$DPaths{"Inc"}};
21195 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21196 }
21197
21198 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021199 my $IncPath = "/usr/include";
21200 if($SystemRoot) {
21201 $IncPath = $SystemRoot.$IncPath;
21202 }
21203 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021204 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021205 }
21206 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021207
21208 if($ExtraInfo)
21209 {
21210 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21211 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021213}
21214
21215sub getLIB_EXT($)
21216{
21217 my $Target = $_[0];
21218 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21219 return $Ext;
21220 }
21221 return $OS_LibExt{$LIB_TYPE}{"default"};
21222}
21223
21224sub getAR_EXT($)
21225{
21226 my $Target = $_[0];
21227 if(my $Ext = $OS_Archive{$Target}) {
21228 return $Ext;
21229 }
21230 return $OS_Archive{"default"};
21231}
21232
21233sub get_dumpversion($)
21234{
21235 my $Cmd = $_[0];
21236 return "" if(not $Cmd);
21237 if($Cache{"get_dumpversion"}{$Cmd}) {
21238 return $Cache{"get_dumpversion"}{$Cmd};
21239 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021240 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021241 chomp($V);
21242 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21243}
21244
21245sub get_dumpmachine($)
21246{
21247 my $Cmd = $_[0];
21248 return "" if(not $Cmd);
21249 if($Cache{"get_dumpmachine"}{$Cmd}) {
21250 return $Cache{"get_dumpmachine"}{$Cmd};
21251 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021252 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021253 chomp($Machine);
21254 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21255}
21256
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021257sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021258{
21259 my $Cmd = $_[0];
21260 return "" if(not $Cmd);
21261 my @Options = (
21262 "--version",
21263 "-help"
21264 );
21265 foreach my $Opt (@Options)
21266 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021267 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021268 if($Info) {
21269 return 1;
21270 }
21271 }
21272 return 0;
21273}
21274
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021275sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021276{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021277 my ($Cmd, $ReqVer) = @_;
21278 return 0 if(not $Cmd or not $ReqVer);
21279 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21280 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021282 if(my $GccVer = get_dumpversion($Cmd))
21283 {
21284 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21285 if(cmpVersions($GccVer, $ReqVer)>=0) {
21286 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21287 }
21288 }
21289 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021290}
21291
21292sub get_depth($)
21293{
21294 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021295 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021296 }
21297 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21298}
21299
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021300sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021301{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021302 return if($Cache{"registerGccHeaders"}); # this function should be called once
21303
21304 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021306 my @Headers = cmd_find($Path,"f");
21307 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21308 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021309 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021310 my $FileName = get_filename($HPath);
21311 if(not defined $DefaultGccHeader{$FileName})
21312 { # skip duplicated
21313 $DefaultGccHeader{$FileName} = $HPath;
21314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021315 }
21316 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021317 $Cache{"registerGccHeaders"} = 1;
21318}
21319
21320sub registerCppHeaders()
21321{
21322 return if($Cache{"registerCppHeaders"}); # this function should be called once
21323
21324 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021325 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021326 my @Headers = cmd_find($CppDir,"f");
21327 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21328 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021329 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021330 my $FileName = get_filename($Path);
21331 if(not defined $DefaultCppHeader{$FileName})
21332 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021333 $DefaultCppHeader{$FileName} = $Path;
21334 }
21335 }
21336 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021337 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021338}
21339
21340sub parse_libname($$$)
21341{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021342 return "" if(not $_[0]);
21343 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21344 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021345 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021346 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21347}
21348
21349sub parse_libname_I($$$)
21350{
21351 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021353 if($Target eq "symbian") {
21354 return parse_libname_symbian($Name, $Type);
21355 }
21356 elsif($Target eq "windows") {
21357 return parse_libname_windows($Name, $Type);
21358 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021359
21360 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021361 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021362 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363 { # libSDL-1.2.so.0.7.1
21364 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021365 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021366 if($Type eq "name")
21367 { # libSDL-1.2
21368 # libwbxml2
21369 return $2;
21370 }
21371 elsif($Type eq "name+ext")
21372 { # libSDL-1.2.so
21373 # libwbxml2.so
21374 return $1;
21375 }
21376 elsif($Type eq "version")
21377 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021378 if(defined $7
21379 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021380 { # 0.7.1
21381 return $7;
21382 }
21383 else
21384 { # libc-2.5.so (=>2.5 version)
21385 my $MV = $5;
21386 $MV=~s/\A[\-\_]+//g;
21387 return $MV;
21388 }
21389 }
21390 elsif($Type eq "short")
21391 { # libSDL
21392 # libwbxml2
21393 return $3;
21394 }
21395 elsif($Type eq "shortest")
21396 { # SDL
21397 # wbxml
21398 return shortest_name($3);
21399 }
21400 }
21401 return "";# error
21402}
21403
21404sub parse_libname_symbian($$)
21405{
21406 my ($Name, $Type) = @_;
21407 my $Ext = getLIB_EXT("symbian");
21408 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21409 { # libpthread{00010001}.dso
21410 if($Type eq "name")
21411 { # libpthread{00010001}
21412 return $2;
21413 }
21414 elsif($Type eq "name+ext")
21415 { # libpthread{00010001}.dso
21416 return $1;
21417 }
21418 elsif($Type eq "version")
21419 { # 00010001
21420 my $V = $4;
21421 $V=~s/\{(.+)\}/$1/;
21422 return $V;
21423 }
21424 elsif($Type eq "short")
21425 { # libpthread
21426 return $3;
21427 }
21428 elsif($Type eq "shortest")
21429 { # pthread
21430 return shortest_name($3);
21431 }
21432 }
21433 return "";# error
21434}
21435
21436sub parse_libname_windows($$)
21437{
21438 my ($Name, $Type) = @_;
21439 my $Ext = getLIB_EXT("windows");
21440 if($Name=~/((.+?)\.$Ext)\Z/)
21441 { # netapi32.dll
21442 if($Type eq "name")
21443 { # netapi32
21444 return $2;
21445 }
21446 elsif($Type eq "name+ext")
21447 { # netapi32.dll
21448 return $1;
21449 }
21450 elsif($Type eq "version")
21451 { # DLL version embedded
21452 # at binary-level
21453 return "";
21454 }
21455 elsif($Type eq "short")
21456 { # netapi32
21457 return $2;
21458 }
21459 elsif($Type eq "shortest")
21460 { # netapi
21461 return shortest_name($2);
21462 }
21463 }
21464 return "";# error
21465}
21466
21467sub shortest_name($)
21468{
21469 my $Name = $_[0];
21470 # remove prefix
21471 $Name=~s/\A(lib|open)//;
21472 # remove suffix
21473 $Name=~s/[\W\d_]+\Z//i;
21474 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21475 return $Name;
21476}
21477
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021478sub createSymbolsList($$$$$)
21479{
21480 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021482 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021483 prepareSymbols(1);
21484
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 my %SymbolHeaderLib = ();
21486 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021488 # Get List
21489 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21490 {
21491 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021492 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021493 next;
21494 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021495 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021496 { # skip other symbols
21497 next;
21498 }
21499 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21500 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021501 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021502 next;
21503 }
21504 my $DyLib = $Symbol_Library{1}{$Symbol};
21505 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021506 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021507 next;
21508 }
21509 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21510 $Total+=1;
21511 }
21512 # Draw List
21513 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21514 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21515 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21516 {
21517 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21518 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021519 my %NS_Symbol = ();
21520 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021521 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021522 }
21523 foreach my $NameSpace (sort keys(%NS_Symbol))
21524 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021525 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021526 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21527 foreach my $Symbol (@SortedInterfaces)
21528 {
21529 my $SubReport = "";
21530 my $Signature = get_Signature($Symbol, 1);
21531 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021532 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021533 }
21534 if($Symbol=~/\A(_Z|\?)/)
21535 {
21536 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021537 $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 +040021538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021539 else {
21540 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21541 }
21542 }
21543 else
21544 {
21545 if($Signature) {
21546 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21547 }
21548 else {
21549 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21550 }
21551 }
21552 $SYMBOLS_LIST .= $SubReport;
21553 }
21554 }
21555 $SYMBOLS_LIST .= "<br/>\n";
21556 }
21557 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021558 # clear info
21559 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21560 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21561 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21562 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021563 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021564 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021565 my $CssStyles = readModule("Styles", "SymbolsList.css");
21566 my $JScripts = readModule("Scripts", "Sections.js");
21567 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021568 my $Title = "$LName: public symbols";
21569 my $Keywords = "$LName, API, symbols";
21570 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021571 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021572 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021573 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021574 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021575 writeFile($SaveTo, $SYMBOLS_LIST);
21576}
21577
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021578sub add_target_libs($)
21579{
21580 foreach (@{$_[0]}) {
21581 $TargetLibs{$_} = 1;
21582 }
21583}
21584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021585sub is_target_lib($)
21586{
21587 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021588 if(not $LName) {
21589 return 0;
21590 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021591 if($OSgroup eq "windows") {
21592 $LName = lc($LName);
21593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594 if($TargetLibraryName
21595 and $LName!~/\Q$TargetLibraryName\E/) {
21596 return 0;
21597 }
21598 if(keys(%TargetLibs)
21599 and not $TargetLibs{$LName}
21600 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21601 return 0;
21602 }
21603 return 1;
21604}
21605
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021606sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021607{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021608 my ($H, $V) = @_;
21609 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021610 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021611 if($TargetHeaders{$V}{$H}) {
21612 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021613 }
21614 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021615 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021616}
21617
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021618sub readLibs($)
21619{
21620 my $LibVersion = $_[0];
21621 if($OStarget eq "windows")
21622 { # dumpbin.exe will crash
21623 # without VS Environment
21624 check_win32_env();
21625 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021626 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021627 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021628 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021629}
21630
21631sub dump_sorting($)
21632{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021633 my $Hash = $_[0];
21634 return [] if(not $Hash);
21635 my @Keys = keys(%{$Hash});
21636 return [] if($#Keys<0);
21637 if($Keys[0]=~/\A\d+\Z/)
21638 { # numbers
21639 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021640 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021641 else
21642 { # strings
21643 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021644 }
21645}
21646
21647sub printMsg($$)
21648{
21649 my ($Type, $Msg) = @_;
21650 if($Type!~/\AINFO/) {
21651 $Msg = $Type.": ".$Msg;
21652 }
21653 if($Type!~/_C\Z/) {
21654 $Msg .= "\n";
21655 }
21656 if($Quiet)
21657 { # --quiet option
21658 appendFile($COMMON_LOG_PATH, $Msg);
21659 }
21660 else
21661 {
21662 if($Type eq "ERROR") {
21663 print STDERR $Msg;
21664 }
21665 else {
21666 print $Msg;
21667 }
21668 }
21669}
21670
21671sub exitStatus($$)
21672{
21673 my ($Code, $Msg) = @_;
21674 printMsg("ERROR", $Msg);
21675 exit($ERROR_CODE{$Code});
21676}
21677
21678sub exitReport()
21679{ # the tool has run without any errors
21680 printReport();
21681 if($COMPILE_ERRORS)
21682 { # errors in headers may add false positives/negatives
21683 exit($ERROR_CODE{"Compile_Error"});
21684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021685 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21686 { # --binary
21687 exit($ERROR_CODE{"Incompatible"});
21688 }
21689 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21690 { # --source
21691 exit($ERROR_CODE{"Incompatible"});
21692 }
21693 elsif($RESULT{"Source"}{"Problems"}
21694 or $RESULT{"Binary"}{"Problems"})
21695 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021696 exit($ERROR_CODE{"Incompatible"});
21697 }
21698 else {
21699 exit($ERROR_CODE{"Compatible"});
21700 }
21701}
21702
21703sub readRules($)
21704{
21705 my $Kind = $_[0];
21706 if(not -f $RULES_PATH{$Kind}) {
21707 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21708 }
21709 my $Content = readFile($RULES_PATH{$Kind});
21710 while(my $Rule = parseTag(\$Content, "rule"))
21711 {
21712 my $RId = parseTag(\$Rule, "id");
21713 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21714 foreach my $Prop (@Properties) {
21715 if(my $Value = parseTag(\$Rule, lc($Prop)))
21716 {
21717 $Value=~s/\n[ ]*//;
21718 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21719 }
21720 }
21721 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21722 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21723 }
21724 else {
21725 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21726 }
21727 }
21728}
21729
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021730sub getReportPath($)
21731{
21732 my $Level = $_[0];
21733 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21734 if($Level eq "Binary")
21735 {
21736 if($BinaryReportPath)
21737 { # --bin-report-path
21738 return $BinaryReportPath;
21739 }
21740 elsif($OutputReportPath)
21741 { # --report-path
21742 return $OutputReportPath;
21743 }
21744 else
21745 { # default
21746 return $Dir."/abi_compat_report.$ReportFormat";
21747 }
21748 }
21749 elsif($Level eq "Source")
21750 {
21751 if($SourceReportPath)
21752 { # --src-report-path
21753 return $SourceReportPath;
21754 }
21755 elsif($OutputReportPath)
21756 { # --report-path
21757 return $OutputReportPath;
21758 }
21759 else
21760 { # default
21761 return $Dir."/src_compat_report.$ReportFormat";
21762 }
21763 }
21764 else
21765 {
21766 if($OutputReportPath)
21767 { # --report-path
21768 return $OutputReportPath;
21769 }
21770 else
21771 { # default
21772 return $Dir."/compat_report.$ReportFormat";
21773 }
21774 }
21775}
21776
21777sub printStatMsg($)
21778{
21779 my $Level = $_[0];
21780 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21781}
21782
21783sub listAffected($)
21784{
21785 my $Level = $_[0];
21786 my $List = "";
21787 foreach (keys(%{$TotalAffected{$Level}}))
21788 {
21789 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21790 { # skip "Low"-severity problems
21791 next;
21792 }
21793 $List .= "$_\n";
21794 }
21795 my $Dir = get_dirname(getReportPath($Level));
21796 if($Level eq "Binary") {
21797 writeFile($Dir."/abi_affected.txt", $List);
21798 }
21799 elsif($Level eq "Source") {
21800 writeFile($Dir."/src_affected.txt", $List);
21801 }
21802}
21803
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021804sub printReport()
21805{
21806 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021807 createReport();
21808 if($JoinReport or $DoubleReport)
21809 {
21810 if($RESULT{"Binary"}{"Problems"}
21811 or $RESULT{"Source"}{"Problems"}) {
21812 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021813 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021814 else {
21815 printMsg("INFO", "result: COMPATIBLE");
21816 }
21817 printStatMsg("Binary");
21818 printStatMsg("Source");
21819 if($ListAffected)
21820 { # --list-affected
21821 listAffected("Binary");
21822 listAffected("Source");
21823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021824 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021825 elsif($BinaryOnly)
21826 {
21827 if($RESULT{"Binary"}{"Problems"}) {
21828 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21829 }
21830 else {
21831 printMsg("INFO", "result: COMPATIBLE");
21832 }
21833 printStatMsg("Binary");
21834 if($ListAffected)
21835 { # --list-affected
21836 listAffected("Binary");
21837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021839 elsif($SourceOnly)
21840 {
21841 if($RESULT{"Source"}{"Problems"}) {
21842 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21843 }
21844 else {
21845 printMsg("INFO", "result: COMPATIBLE");
21846 }
21847 printStatMsg("Source");
21848 if($ListAffected)
21849 { # --list-affected
21850 listAffected("Source");
21851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021853 if($StdOut)
21854 {
21855 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021856 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021857 printMsg("INFO", "compatibility report has been generated to stdout");
21858 }
21859 else
21860 { # default
21861 printMsg("INFO", "compatibility reports have been generated to stdout");
21862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021864 else
21865 {
21866 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021867 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021868 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21869 }
21870 elsif($DoubleReport)
21871 { # default
21872 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21873 }
21874 elsif($BinaryOnly)
21875 { # --binary
21876 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21877 }
21878 elsif($SourceOnly)
21879 { # --source
21880 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021882 }
21883}
21884
21885sub check_win32_env()
21886{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021887 if(not $ENV{"VCINSTALLDIR"}
21888 or not $ENV{"INCLUDE"}) {
21889 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021890 }
21891}
21892
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021893sub diffSets($$)
21894{
21895 my ($S1, $S2) = @_;
21896 my @SK1 = keys(%{$S1});
21897 my @SK2 = keys(%{$S2});
21898 if($#SK1!=$#SK2) {
21899 return 1;
21900 }
21901 foreach my $K1 (@SK1)
21902 {
21903 if(not defined $S2->{$K1}) {
21904 return 1;
21905 }
21906 }
21907 return 0;
21908}
21909
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021910sub defaultDumpPath($$)
21911{
21912 my ($N, $V) = @_;
21913 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21914}
21915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021916sub create_ABI_Dump()
21917{
21918 if(not -e $DumpAPI) {
21919 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21920 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021921
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021922 if(isDump($DumpAPI)) {
21923 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021924 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021925 else {
21926 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021927 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021928
21929 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021930 { # set to default: N
21931 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021932 }
21933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021934 initLogging(1);
21935 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021936
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021937 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021938 if($OutputDumpPath)
21939 { # user defined path
21940 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021941 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021942 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21943
21944 if(not $Archive and not $StdOut)
21945 { # check archive utilities
21946 if($OSgroup eq "windows")
21947 { # using zip
21948 my $ZipCmd = get_CmdPath("zip");
21949 if(not $ZipCmd) {
21950 exitStatus("Not_Found", "can't find \"zip\"");
21951 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021952 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021953 else
21954 { # using tar and gzip
21955 my $TarCmd = get_CmdPath("tar");
21956 if(not $TarCmd) {
21957 exitStatus("Not_Found", "can't find \"tar\"");
21958 }
21959 my $GzipCmd = get_CmdPath("gzip");
21960 if(not $GzipCmd) {
21961 exitStatus("Not_Found", "can't find \"gzip\"");
21962 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021963 }
21964 }
21965
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021966 if(not $Descriptor{1}{"Dump"})
21967 {
21968 if(not $CheckHeadersOnly) {
21969 readLibs(1);
21970 }
21971 if($CheckHeadersOnly) {
21972 setLanguage(1, "C++");
21973 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021974 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021975 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021976 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021977 if(not $Descriptor{1}{"Dump"})
21978 {
21979 if($Descriptor{1}{"Headers"}) {
21980 readHeaders(1);
21981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021982 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021983 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021984 if(not keys(%{$SymbolInfo{1}}))
21985 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021986 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021987 {
21988 if($CheckHeadersOnly) {
21989 exitStatus("Empty_Set", "the set of public symbols is empty");
21990 }
21991 else {
21992 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21993 }
21994 }
21995 }
21996 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021997 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021998 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21999 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022000 if($ExtraDump)
22001 { # add unmangled names to the ABI dump
22002 my @Names = ();
22003 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22004 {
22005 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22006 push(@Names, $MnglName);
22007 }
22008 }
22009 translateSymbols(@Names, 1);
22010 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22011 {
22012 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22013 {
22014 if(my $Unmangled = $tr_name{$MnglName})
22015 {
22016 if($MnglName ne $Unmangled) {
22017 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22018 }
22019 }
22020 }
22021 }
22022 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022023
22024 my %GccConstants = (); # built-in GCC constants
22025 foreach my $Name (keys(%{$Constants{1}}))
22026 {
22027 if(not defined $Constants{1}{$Name}{"Header"})
22028 {
22029 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22030 delete($Constants{1}{$Name});
22031 }
22032 }
22033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022034 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022035 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022036 "TypeInfo" => $TypeInfo{1},
22037 "SymbolInfo" => $SymbolInfo{1},
22038 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022039 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022040 "SymbolVersion" => $SymVer{1},
22041 "LibraryVersion" => $Descriptor{1}{"Version"},
22042 "LibraryName" => $TargetLibraryName,
22043 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022044 "SkipTypes" => $SkipTypes{1},
22045 "SkipSymbols" => $SkipSymbols{1},
22046 "SkipNameSpaces" => $SkipNameSpaces{1},
22047 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022048 "Headers" => \%HeadersInfo,
22049 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022050 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022051 "NameSpaces" => $NestedNameSpaces{1},
22052 "Target" => $OStarget,
22053 "Arch" => getArch(1),
22054 "WordSize" => $WORD_SIZE{1},
22055 "GccVersion" => get_dumpversion($GCC_PATH),
22056 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22057 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22058 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022059 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022060 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022061 }
22062 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022063 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022065 if($ExtendedCheck)
22066 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022067 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022068 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022069 if($BinaryOnly)
22070 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022071 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022072 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022073 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022074 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022075 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022076 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22077 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022078 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022079
22080 my $ABI_DUMP = "";
22081 if($UseXML)
22082 {
22083 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022084 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022086 else
22087 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022088 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022090 if($StdOut)
22091 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022092 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022093 printMsg("INFO", "ABI dump has been generated to stdout");
22094 return;
22095 }
22096 else
22097 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022098 my ($DDir, $DName) = separate_path($DumpPath);
22099 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022100 if(not $Archive) {
22101 $DPath = $DumpPath;
22102 }
22103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022104 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022105
22106 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022107 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022108 close(DUMP);
22109
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022110 if(not -s $DPath) {
22111 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22112 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022113 if($Archive) {
22114 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022115 }
22116
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022117 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022118 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022119 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022120 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022121 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022122 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022123 # 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 +040022124 }
22125}
22126
22127sub quickEmptyReports()
22128{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022129 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022130 # NOTE: the dump contains the "LibraryVersion" attribute
22131 # if you change the version, then your dump will be different
22132 # OVERCOME: use -v1 and v2 options for comparing dumps
22133 # and don't change version in the XML descriptor (and dumps)
22134 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022135 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22136 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022137 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022138 my $FilePath1 = $Descriptor{1}{"Path"};
22139 my $FilePath2 = $Descriptor{2}{"Path"};
22140
22141 if(not isDump_U($FilePath1)) {
22142 $FilePath1 = unpackDump($FilePath1);
22143 }
22144
22145 if(not isDump_U($FilePath2)) {
22146 $FilePath2 = unpackDump($FilePath2);
22147 }
22148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022149 if($FilePath1 and $FilePath2)
22150 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022151 my $Line = readLineNum($FilePath1, 0);
22152 if($Line=~/xml/)
22153 { # XML format
22154 # is not supported yet
22155 return;
22156 }
22157
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022158 local $/ = undef;
22159
22160 open(DUMP1, $FilePath1);
22161 my $Content1 = <DUMP1>;
22162 close(DUMP1);
22163
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022164 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022165
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022166 if($FilePath1 eq $FilePath2) {
22167 $Eq = 1;
22168 }
22169
22170 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022171 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022172 open(DUMP2, $FilePath2);
22173 my $Content2 = <DUMP2>;
22174 close(DUMP2);
22175
22176 if($Content1 eq $Content2) {
22177 $Eq = 1;
22178 }
22179
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022180 # clean memory
22181 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022182 }
22183
22184 if($Eq)
22185 {
22186 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022187 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022188 my $ABIdump = eval($Content1);
22189
22190 # clean memory
22191 undef $Content1;
22192
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022193 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022194 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 +040022195 }
22196 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022197 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022198 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22199 }
22200 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022201 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022202 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22203 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022204 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022205
22206 foreach (keys(%{$Registered_Headers{1}})) {
22207 $TargetHeaders{1}{$_} = 1;
22208 }
22209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022210 read_Libs_DumpInfo($ABIdump, 1);
22211 read_Machine_DumpInfo($ABIdump, 1);
22212 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022213
22214 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22215 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22216
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022217 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22218 {
22219 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22220 {
22221 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22222 next;
22223 }
22224 }
22225
22226 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22227 if($Access ne "private")
22228 {
22229 $CheckedSymbols{"Binary"}{$S} = 1;
22230 $CheckedSymbols{"Source"}{$S} = 1;
22231 }
22232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022234 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22235 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022236
22237 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22238 {
22239 $UsedDump{1}{"DWARF"} = 1;
22240 $UsedDump{2}{"DWARF"} = 1;
22241
22242 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22243 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22244 }
22245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022246 exitReport();
22247 }
22248 }
22249 }
22250}
22251
22252sub initLogging($)
22253{
22254 my $LibVersion = $_[0];
22255 # create log directory
22256 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22257 if($OutputLogPath{$LibVersion})
22258 { # user-defined by -log-path option
22259 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22260 }
22261 if($LogMode ne "n") {
22262 mkpath($LOG_DIR);
22263 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022264 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022265 if($Debug)
22266 { # debug directory
22267 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022268
22269 if(not $ExtraInfo)
22270 { # enable --extra-info
22271 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022273 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022274 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022275}
22276
22277sub writeLog($$)
22278{
22279 my ($LibVersion, $Msg) = @_;
22280 if($LogMode ne "n") {
22281 appendFile($LOG_PATH{$LibVersion}, $Msg);
22282 }
22283}
22284
22285sub resetLogging($)
22286{
22287 my $LibVersion = $_[0];
22288 if($LogMode!~/a|n/)
22289 { # remove old log
22290 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022291 if($Debug) {
22292 rmtree($DEBUG_PATH{$LibVersion});
22293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022294 }
22295}
22296
22297sub printErrorLog($)
22298{
22299 my $LibVersion = $_[0];
22300 if($LogMode ne "n") {
22301 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22302 }
22303}
22304
22305sub isDump($)
22306{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022307 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22308 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022309 return $1;
22310 }
22311 return 0;
22312}
22313
22314sub isDump_U($)
22315{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022316 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 return $1;
22318 }
22319 return 0;
22320}
22321
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022322sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022323{
22324 # read input XML descriptors or ABI dumps
22325 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022326 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022327 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022328 if(not -e $Descriptor{1}{"Path"}) {
22329 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022330 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022332 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022333 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022334 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022335 if(not -e $Descriptor{2}{"Path"}) {
22336 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022337 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022339 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022340
22341 if(not defined $DisableQuickEmptyReport)
22342 {
22343 if(isDump($Descriptor{1}{"Path"})
22344 and isDump($Descriptor{2}{"Path"}))
22345 { # optimization: equal ABI dumps
22346 quickEmptyReports();
22347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022348 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022350 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022351
22352 if(isDump($Descriptor{1}{"Path"})) {
22353 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022354 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022355 else {
22356 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22357 }
22358
22359 if(isDump($Descriptor{2}{"Path"})) {
22360 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22361 }
22362 else {
22363 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022364 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022365
22366 if(not $Descriptor{1}{"Version"})
22367 { # set to default: X
22368 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022369 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022370 }
22371
22372 if(not $Descriptor{2}{"Version"})
22373 { # set to default: Y
22374 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022375 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022376 }
22377
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022378 if(not $UsedDump{1}{"V"}) {
22379 initLogging(1);
22380 }
22381
22382 if(not $UsedDump{2}{"V"}) {
22383 initLogging(2);
22384 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022385
22386 # check input data
22387 if(not $Descriptor{1}{"Headers"}) {
22388 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022389 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022390 if(not $Descriptor{2}{"Headers"}) {
22391 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022392 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022393
22394 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022395 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022396 if(not $Descriptor{1}{"Libs"}) {
22397 exitStatus("Error", "can't find libraries info in descriptor d1");
22398 }
22399 if(not $Descriptor{2}{"Libs"}) {
22400 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022401 }
22402 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022403
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022404 if($UseDumps)
22405 { # --use-dumps
22406 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022407 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22408 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022409
22410 unlink($DumpPath1);
22411 unlink($DumpPath2);
22412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022413 my $pid = fork();
22414 if($pid)
22415 { # dump on two CPU cores
22416 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22417 if($RelativeDirectory{1}) {
22418 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22419 }
22420 if($OutputLogPath{1}) {
22421 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22422 }
22423 if($CrossGcc) {
22424 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22425 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022426 if($Quiet)
22427 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022428 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022429 @PARAMS = (@PARAMS, "-logging-mode", "a");
22430 }
22431 elsif($LogMode and $LogMode ne "w")
22432 { # "w" is default
22433 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022434 }
22435 if($ExtendedCheck) {
22436 @PARAMS = (@PARAMS, "-extended");
22437 }
22438 if($UserLang) {
22439 @PARAMS = (@PARAMS, "-lang", $UserLang);
22440 }
22441 if($TargetVersion{1}) {
22442 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22443 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022444 if($BinaryOnly) {
22445 @PARAMS = (@PARAMS, "-binary");
22446 }
22447 if($SourceOnly) {
22448 @PARAMS = (@PARAMS, "-source");
22449 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022450 if($SortDump) {
22451 @PARAMS = (@PARAMS, "-sort");
22452 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022453 if($DumpFormat and $DumpFormat ne "perl") {
22454 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22455 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022456 if($CheckHeadersOnly) {
22457 @PARAMS = (@PARAMS, "-headers-only");
22458 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022459 if($Debug)
22460 {
22461 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022462 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022464 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022465 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022466 exit(1);
22467 }
22468 }
22469 else
22470 { # child
22471 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22472 if($RelativeDirectory{2}) {
22473 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22474 }
22475 if($OutputLogPath{2}) {
22476 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22477 }
22478 if($CrossGcc) {
22479 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22480 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022481 if($Quiet)
22482 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022483 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022484 @PARAMS = (@PARAMS, "-logging-mode", "a");
22485 }
22486 elsif($LogMode and $LogMode ne "w")
22487 { # "w" is default
22488 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022489 }
22490 if($ExtendedCheck) {
22491 @PARAMS = (@PARAMS, "-extended");
22492 }
22493 if($UserLang) {
22494 @PARAMS = (@PARAMS, "-lang", $UserLang);
22495 }
22496 if($TargetVersion{2}) {
22497 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22498 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022499 if($BinaryOnly) {
22500 @PARAMS = (@PARAMS, "-binary");
22501 }
22502 if($SourceOnly) {
22503 @PARAMS = (@PARAMS, "-source");
22504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022505 if($SortDump) {
22506 @PARAMS = (@PARAMS, "-sort");
22507 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022508 if($DumpFormat and $DumpFormat ne "perl") {
22509 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22510 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022511 if($CheckHeadersOnly) {
22512 @PARAMS = (@PARAMS, "-headers-only");
22513 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022514 if($Debug)
22515 {
22516 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022517 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022519 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022520 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022521 exit(1);
22522 }
22523 else {
22524 exit(0);
22525 }
22526 }
22527 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022529 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022530 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22531 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022532 if($TargetTitle ne $TargetLibraryName) {
22533 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022534 }
22535 if($ShowRetVal) {
22536 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22537 }
22538 if($CrossGcc) {
22539 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22540 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022541 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22542 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022543 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022544 }
22545 if($ReportFormat and $ReportFormat ne "html")
22546 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022547 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22548 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022549 if($OutputReportPath) {
22550 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22551 }
22552 if($BinaryReportPath) {
22553 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22554 }
22555 if($SourceReportPath) {
22556 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22557 }
22558 if($LoggingPath) {
22559 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22560 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022561 if($CheckHeadersOnly) {
22562 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22563 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022564 if($BinaryOnly) {
22565 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22566 }
22567 if($SourceOnly) {
22568 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22569 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022570 if($Debug)
22571 {
22572 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22573 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 system("perl", $0, @CMP_PARAMS);
22576 exit($?>>8);
22577 }
22578 if(not $Descriptor{1}{"Dump"}
22579 or not $Descriptor{2}{"Dump"})
22580 { # need GCC toolchain to analyze
22581 # header files and libraries
22582 detect_default_paths("inc|lib|gcc");
22583 }
22584 if(not $Descriptor{1}{"Dump"})
22585 {
22586 if(not $CheckHeadersOnly) {
22587 readLibs(1);
22588 }
22589 if($CheckHeadersOnly) {
22590 setLanguage(1, "C++");
22591 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022592 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022593 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022594 }
22595 if(not $Descriptor{2}{"Dump"})
22596 {
22597 if(not $CheckHeadersOnly) {
22598 readLibs(2);
22599 }
22600 if($CheckHeadersOnly) {
22601 setLanguage(2, "C++");
22602 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022603 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022604 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022605 }
22606 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22607 { # support for old ABI dumps
22608 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022609 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022610 {
22611 $WORD_SIZE{1} = $WORD_SIZE{2};
22612 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22613 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022614 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022615 {
22616 $WORD_SIZE{2} = $WORD_SIZE{1};
22617 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22618 }
22619 }
22620 elsif(not $WORD_SIZE{1}
22621 and not $WORD_SIZE{2})
22622 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022623 $WORD_SIZE{1} = "4";
22624 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022625 }
22626 if($Descriptor{1}{"Dump"})
22627 { # support for old ABI dumps
22628 prepareTypes(1);
22629 }
22630 if($Descriptor{2}{"Dump"})
22631 { # support for old ABI dumps
22632 prepareTypes(2);
22633 }
22634 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22635 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22636 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022637 # process input data
22638 if($Descriptor{1}{"Headers"}
22639 and not $Descriptor{1}{"Dump"}) {
22640 readHeaders(1);
22641 }
22642 if($Descriptor{2}{"Headers"}
22643 and not $Descriptor{2}{"Dump"}) {
22644 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022645 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022646
22647 # clean memory
22648 %SystemHeaders = ();
22649 %mangled_name_gcc = ();
22650
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022651 prepareSymbols(1);
22652 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022653
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022654 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022655 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022656
22657 # Virtual Tables
22658 registerVTable(1);
22659 registerVTable(2);
22660
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022661 if(not checkDump(1, "1.22")
22662 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022663 { # support for old ABI dumps
22664 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22665 {
22666 if($ClassName=~/</)
22667 { # templates
22668 if(not defined $VirtualTable{1}{$ClassName})
22669 { # synchronize
22670 delete($VirtualTable{2}{$ClassName});
22671 }
22672 }
22673 }
22674 }
22675
22676 registerOverriding(1);
22677 registerOverriding(2);
22678
22679 setVirtFuncPositions(1);
22680 setVirtFuncPositions(2);
22681
22682 # Other
22683 addParamNames(1);
22684 addParamNames(2);
22685
22686 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022687}
22688
22689sub compareAPIs($)
22690{
22691 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022692
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022693 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022694 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022695
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022696 if($Level eq "Binary") {
22697 printMsg("INFO", "comparing ABIs ...");
22698 }
22699 else {
22700 printMsg("INFO", "comparing APIs ...");
22701 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022702
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022703 if($CheckHeadersOnly
22704 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022705 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022706 detectAdded_H($Level);
22707 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022708 }
22709 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022710 { # added/removed in libs
22711 detectAdded($Level);
22712 detectRemoved($Level);
22713 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022714
22715 mergeSymbols($Level);
22716 if(keys(%{$CheckedSymbols{$Level}})) {
22717 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022718 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022719
22720 $Cache{"mergeTypes"} = (); # free memory
22721
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022722 if($CheckHeadersOnly
22723 or $Level eq "Source")
22724 { # added/removed in headers
22725 mergeHeaders($Level);
22726 }
22727 else
22728 { # added/removed in libs
22729 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022730 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022731
22732 foreach my $S (keys(%{$CompatProblems{$Level}}))
22733 {
22734 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22735 {
22736 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22737 {
22738 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22739 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22740 }
22741 }
22742 }
22743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022744}
22745
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022746sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022747{
22748 my %Opts = (
22749 "OStarget"=>$OStarget,
22750 "Debug"=>$Debug,
22751 "Quiet"=>$Quiet,
22752 "LogMode"=>$LogMode,
22753 "CheckHeadersOnly"=>$CheckHeadersOnly,
22754
22755 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022756 "GCC_PATH"=>$GCC_PATH,
22757 "TargetSysInfo"=>$TargetSysInfo,
22758 "CrossPrefix"=>$CrossPrefix,
22759 "TargetLibraryName"=>$TargetLibraryName,
22760 "CrossGcc"=>$CrossGcc,
22761 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022762 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022763 "CppCompat"=>$CppCompat,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022764
22765 "BinaryOnly" => $BinaryOnly,
22766 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022767 );
22768 return \%Opts;
22769}
22770
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022771sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022772{
22773 my %CODE_ERROR = reverse(%ERROR_CODE);
22774 return $CODE_ERROR{$_[0]};
22775}
22776
22777sub scenario()
22778{
22779 if($StdOut)
22780 { # enable quiet mode
22781 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022782 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022783 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022784 if(not $LogMode)
22785 { # default
22786 $LogMode = "w";
22787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022788 if($UserLang)
22789 { # --lang=C++
22790 $UserLang = uc($UserLang);
22791 $COMMON_LANGUAGE{1}=$UserLang;
22792 $COMMON_LANGUAGE{2}=$UserLang;
22793 }
22794 if($LoggingPath)
22795 {
22796 $OutputLogPath{1} = $LoggingPath;
22797 $OutputLogPath{2} = $LoggingPath;
22798 if($Quiet) {
22799 $COMMON_LOG_PATH = $LoggingPath;
22800 }
22801 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022802
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022803 if($Quick) {
22804 $ADD_TMPL_INSTANCES = 0;
22805 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022806 if($OutputDumpPath)
22807 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022808 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022809 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22810 }
22811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022812 if($BinaryOnly and $SourceOnly)
22813 { # both --binary and --source
22814 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022815 if(not $CmpSystems)
22816 {
22817 $BinaryOnly = 0;
22818 $SourceOnly = 0;
22819 }
22820
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022821 $DoubleReport = 1;
22822 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022823
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022824 if($OutputReportPath)
22825 { # --report-path
22826 $DoubleReport = 0;
22827 $JoinReport = 1;
22828 }
22829 }
22830 elsif($BinaryOnly or $SourceOnly)
22831 { # --binary or --source
22832 $DoubleReport = 0;
22833 $JoinReport = 0;
22834 }
22835 if($UseXML)
22836 { # --xml option
22837 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022838 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022840 if($ReportFormat)
22841 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022842 $ReportFormat = lc($ReportFormat);
22843 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022844 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022846 if($ReportFormat eq "htm")
22847 { # HTM == HTML
22848 $ReportFormat = "html";
22849 }
22850 elsif($ReportFormat eq "xml")
22851 { # --report-format=XML equal to --xml
22852 $UseXML = 1;
22853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022854 }
22855 else
22856 { # default: HTML
22857 $ReportFormat = "html";
22858 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022859 if($DumpFormat)
22860 { # validate
22861 $DumpFormat = lc($DumpFormat);
22862 if($DumpFormat!~/\A(xml|perl)\Z/) {
22863 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22864 }
22865 if($DumpFormat eq "xml")
22866 { # --dump-format=XML equal to --xml
22867 $UseXML = 1;
22868 }
22869 }
22870 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022871 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022872 $DumpFormat = "perl";
22873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022874 if($Quiet and $LogMode!~/a|n/)
22875 { # --quiet log
22876 if(-f $COMMON_LOG_PATH) {
22877 unlink($COMMON_LOG_PATH);
22878 }
22879 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022880 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022881 $CheckUndefined = 1;
22882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022883 if($TestTool and $UseDumps)
22884 { # --test && --use-dumps == --test-dump
22885 $TestDump = 1;
22886 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022887 if($Tolerant)
22888 { # enable all
22889 $Tolerance = 1234;
22890 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022891 if($Help)
22892 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022893 HELP_MESSAGE();
22894 exit(0);
22895 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022896 if($InfoMsg)
22897 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022898 INFO_MESSAGE();
22899 exit(0);
22900 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022901 if($ShowVersion)
22902 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022903 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 +040022904 exit(0);
22905 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022906 if($DumpVersion)
22907 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022908 printMsg("INFO", $TOOL_VERSION);
22909 exit(0);
22910 }
22911 if($ExtendedCheck) {
22912 $CheckHeadersOnly = 1;
22913 }
22914 if($SystemRoot_Opt)
22915 { # user defined root
22916 if(not -e $SystemRoot_Opt) {
22917 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22918 }
22919 $SystemRoot = $SystemRoot_Opt;
22920 $SystemRoot=~s/[\/]+\Z//g;
22921 if($SystemRoot) {
22922 $SystemRoot = get_abs_path($SystemRoot);
22923 }
22924 }
22925 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022926
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022927 if($SortDump)
22928 {
22929 $Data::Dumper::Useperl = 1;
22930 $Data::Dumper::Sortkeys = \&dump_sorting;
22931 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022933 if($TargetLibsPath)
22934 {
22935 if(not -f $TargetLibsPath) {
22936 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22937 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022938 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
22939 {
22940 if($OSgroup eq "windows") {
22941 $TargetLibs{lc($Lib)} = 1;
22942 }
22943 else {
22944 $TargetLibs{$Lib} = 1;
22945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022946 }
22947 }
22948 if($TargetHeadersPath)
22949 { # --headers-list
22950 if(not -f $TargetHeadersPath) {
22951 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22952 }
22953 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22954 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022955 $TargetHeaders{1}{get_filename($Header)} = 1;
22956 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022957 }
22958 }
22959 if($TargetHeader)
22960 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022961 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22962 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022963 }
22964 if($TestTool
22965 or $TestDump)
22966 { # --test, --test-dump
22967 detect_default_paths("bin|gcc"); # to compile libs
22968 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022969 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030022970 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022971 exit(0);
22972 }
22973 if($DumpSystem)
22974 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022975 if(-d $MODULES_DIR."/Targets/"
22976 and -d $MODULES_DIR."/Targets/".$OStarget) {
22977 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
22978 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022979 if(not $TargetSysInfo) {
22980 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22981 }
22982
22983 if(not -d $TargetSysInfo) {
22984 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22985 }
22986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022987 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022988 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022989 { # system XML descriptor
22990 if(not -f $DumpSystem) {
22991 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22992 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022993
22994 my $SDesc = readFile($DumpSystem);
22995 if(my $RelDir = $RelativeDirectory{1}) {
22996 $SDesc =~ s/{RELPATH}/$RelDir/g;
22997 }
22998
22999 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023000 foreach (@{$Ret->{"Tools"}})
23001 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023002 push_U($SystemPaths{"bin"}, $_);
23003 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023004 }
23005 if($Ret->{"CrossPrefix"}) {
23006 $CrossPrefix = $Ret->{"CrossPrefix"};
23007 }
23008 }
23009 elsif($SystemRoot_Opt)
23010 { # -sysroot "/" option
23011 # default target: /usr/lib, /usr/include
23012 # search libs: /usr/lib and /lib
23013 if(not -e $SystemRoot."/usr/lib") {
23014 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23015 }
23016 if(not -e $SystemRoot."/lib") {
23017 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23018 }
23019 if(not -e $SystemRoot."/usr/include") {
23020 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23021 }
23022 readSystemDescriptor("
23023 <name>
23024 $DumpSystem
23025 </name>
23026 <headers>
23027 $SystemRoot/usr/include
23028 </headers>
23029 <libs>
23030 $SystemRoot/usr/lib
23031 </libs>
23032 <search_libs>
23033 $SystemRoot/lib
23034 </search_libs>");
23035 }
23036 else {
23037 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23038 }
23039 detect_default_paths("bin|gcc"); # to check symbols
23040 if($OStarget eq "windows")
23041 { # to run dumpbin.exe
23042 # and undname.exe
23043 check_win32_env();
23044 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023045 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023046 exit(0);
23047 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023048
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023049 if($CmpSystems)
23050 { # --cmp-systems
23051 detect_default_paths("bin"); # to extract dumps
23052 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023053 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023054 exit(0);
23055 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023056
23057 if(not $CountSymbols)
23058 {
23059 if(not $TargetLibraryName) {
23060 exitStatus("Error", "library name is not selected (-l option)");
23061 }
23062 else
23063 { # validate library name
23064 if($TargetLibraryName=~/[\*\/\\]/) {
23065 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23066 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023067 }
23068 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023069
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023070 if(not $TargetTitle) {
23071 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023072 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023073
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023074 if($SymbolsListPath)
23075 {
23076 if(not -f $SymbolsListPath) {
23077 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23078 }
23079 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23080 $SymbolsList{$Interface} = 1;
23081 }
23082 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023083 if($TypesListPath)
23084 {
23085 if(not -f $TypesListPath) {
23086 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23087 }
23088 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23089 $TypesList{$Type} = 1;
23090 }
23091 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023092 if($SkipSymbolsListPath)
23093 {
23094 if(not -f $SkipSymbolsListPath) {
23095 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23096 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023097 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23098 {
23099 $SkipSymbols{1}{$Interface} = 1;
23100 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023101 }
23102 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023103 if($SkipTypesListPath)
23104 {
23105 if(not -f $SkipTypesListPath) {
23106 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23107 }
23108 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23109 {
23110 $SkipTypes{1}{$Type} = 1;
23111 $SkipTypes{2}{$Type} = 1;
23112 }
23113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023114 if($SkipHeadersPath)
23115 {
23116 if(not -f $SkipHeadersPath) {
23117 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23118 }
23119 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023120 { # register for both versions
23121 $SkipHeadersList{1}{$Path} = 1;
23122 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023124 my ($CPath, $Type) = classifyPath($Path);
23125 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023126 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023127 }
23128 }
23129 if($ParamNamesPath)
23130 {
23131 if(not -f $ParamNamesPath) {
23132 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23133 }
23134 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23135 {
23136 if($Line=~s/\A(\w+)\;//)
23137 {
23138 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023139 if($Line=~/;(\d+);/)
23140 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023141 while($Line=~s/(\d+);(\w+)//) {
23142 $AddIntParams{$Interface}{$1}=$2;
23143 }
23144 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023145 else
23146 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023147 my $Num = 0;
23148 foreach my $Name (split(/;/, $Line)) {
23149 $AddIntParams{$Interface}{$Num++}=$Name;
23150 }
23151 }
23152 }
23153 }
23154 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023156 if($AppPath)
23157 {
23158 if(not -f $AppPath) {
23159 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23160 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023161
23162 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023163 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023164 $SymbolsList_App{$Interface} = 1;
23165 }
23166 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023167
23168 if($CountSymbols)
23169 {
23170 if(not -e $CountSymbols) {
23171 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23172 }
23173
23174 read_ABI_Dump(1, $CountSymbols);
23175
23176 foreach my $Id (keys(%{$SymbolInfo{1}}))
23177 {
23178 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23179 if(not $MnglName) {
23180 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23181 }
23182
23183 if(my $SV = $SymVer{1}{$MnglName}) {
23184 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23185 }
23186 else {
23187 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23188 }
23189
23190 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23191 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23192 }
23193 }
23194
23195 my $Count = 0;
23196 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23197 {
23198 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23199 next;
23200 }
23201 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23202 next;
23203 }
23204 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23205 next;
23206 }
23207
23208 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23209 }
23210
23211 printMsg("INFO", $Count);
23212 exit(0);
23213 }
23214
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023215 if($DumpAPI)
23216 { # --dump-abi
23217 # make an API dump
23218 create_ABI_Dump();
23219 exit($COMPILE_ERRORS);
23220 }
23221 # default: compare APIs
23222 # -d1 <path>
23223 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023224 compareInit();
23225 if($JoinReport or $DoubleReport)
23226 {
23227 compareAPIs("Binary");
23228 compareAPIs("Source");
23229 }
23230 elsif($BinaryOnly) {
23231 compareAPIs("Binary");
23232 }
23233 elsif($SourceOnly) {
23234 compareAPIs("Source");
23235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023236 exitReport();
23237}
23238
23239scenario();