blob: 602cb5692afdae8be740730563f2c9aacf9780e8 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko8580e852016-08-19 19:11:48 +03003# ABI Compliance Checker (ABICC) 1.99.24
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040020# - G++ (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030024# - ABI Dumper (0.99.15 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040025#
26# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040027# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040028# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040029#
30# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040031# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040032# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040033# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030034# - Sigcheck v2.52 or newer
35# - GnuWin Zip and UnZip
36# - Exuberant Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040037# - Add tool locations to the PATH environment variable
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030038# - Run vcvars64.bat (C:\Microsoft Visual Studio 9.0\VC\bin\)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040039#
40# This program is free software: you can redistribute it and/or modify
41# it under the terms of the GNU General Public License or the GNU Lesser
42# General Public License as published by the Free Software Foundation.
43#
44# This program is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47# GNU General Public License for more details.
48#
49# You should have received a copy of the GNU General Public License
50# and the GNU Lesser General Public License along with this program.
51# If not, see <http://www.gnu.org/licenses/>.
52###########################################################################
53use Getopt::Long;
54Getopt::Long::Configure ("posix_default", "no_ignore_case");
55use File::Path qw(mkpath rmtree);
56use File::Temp qw(tempdir);
57use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040058use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040059use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040060use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040061use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040062
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030063my $TOOL_VERSION = "1.99.24";
64my $ABI_DUMP_VERSION = "3.3";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey 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,
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030095$DisableQuickEmptyReport, $SkipTypedefUncover);
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 Ponomarenko8580e852016-08-19 19:11:48 +0300259 "skip-typedef-uncover!" => \$SkipTypedefUncover,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300260 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400261) or ERR_MESSAGE();
262
263sub ERR_MESSAGE()
264{
265 printMsg("INFO", "\n".$ShortUsage);
266 exit($ERROR_CODE{"Error"});
267}
268
269my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
270my $SLIB_TYPE = $LIB_TYPE;
271if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
272{ # show as "shared" library
273 $SLIB_TYPE = "shared";
274}
275my $LIB_EXT = getLIB_EXT($OSgroup);
276my $AR_EXT = getAR_EXT($OSgroup);
277my $BYTE_SIZE = 8;
278my $COMMON_LOG_PATH = "logs/run.log";
279
280my $HelpMessage="
281NAME:
282 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400283 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400284
285DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400286 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400287 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
288 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
289 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
290 and/or source-level compatibility: changes in calling stack, v-table changes,
291 removed symbols, renamed fields, etc. Binary incompatibility may result in
292 crashing or incorrect behavior of applications built with an old version of
293 a library if they run on a new one. Source incompatibility may result in
294 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400295
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400296 The tool is intended for developers of software libraries and maintainers
297 of operating systems who are interested in ensuring backward compatibility,
298 i.e. allow old applications to run or to be recompiled with newer library
299 versions.
300
301 Also the tool can be used by ISVs for checking applications portability to
302 new library versions. Found issues can be taken into account when adapting
303 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400304
305 This tool is free software: you can redistribute it and/or modify it
306 under the terms of the GNU LGPL or GNU GPL.
307
308USAGE:
309 $CmdName [options]
310
311EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400312 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400313
314 OLD.xml and NEW.xml are XML-descriptors:
315
316 <version>
317 1.0
318 </version>
319
320 <headers>
321 /path1/to/header(s)/
322 /path2/to/header(s)/
323 ...
324 </headers>
325
326 <libs>
327 /path1/to/library(ies)/
328 /path2/to/library(ies)/
329 ...
330 </libs>
331
332INFORMATION OPTIONS:
333 -h|-help
334 Print this help.
335
336 -i|-info
337 Print complete info.
338
339 -v|-version
340 Print version information.
341
342 -dumpversion
343 Print the tool version ($TOOL_VERSION) and don't do anything else.
344
345GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400346 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400347 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400348
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400349 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400350 Descriptor of 1st (old) library version.
351 It may be one of the following:
352
353 1. XML-descriptor (VERSION.xml file):
354
355 <version>
356 1.0
357 </version>
358
359 <headers>
360 /path1/to/header(s)/
361 /path2/to/header(s)/
362 ...
363 </headers>
364
365 <libs>
366 /path1/to/library(ies)/
367 /path2/to/library(ies)/
368 ...
369 </libs>
370
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300371 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400372
373 2. ABI dump generated by -dump option
374 3. Directory with headers and/or $SLIB_TYPE libraries
375 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400376
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300377 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400378 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379
380 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400381 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400382
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400383 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400384 Descriptor of 2nd (new) library version.
385
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400386 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400387 Create library ABI dump for the input XML descriptor. You can
388 transfer it anywhere and pass instead of the descriptor. Also
389 it can be used for debugging the tool.
390
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300391 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400392
393sub HELP_MESSAGE() {
394 printMsg("INFO", $HelpMessage."
395MORE INFO:
396 $CmdName --info\n");
397}
398
399sub INFO_MESSAGE()
400{
401 printMsg("INFO", "$HelpMessage
402EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400403 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300404 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400405 for portability to the new library version.
406
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300407 -static
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408 Check static libraries instead of the shared ones. The <libs> section
409 of the XML-descriptor should point to static libraries location.
410
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300411 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400412 Path to the cross GCC compiler to use instead of the usual (host) GCC.
413
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300414 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300416
417 -gcc-options OPTS
418 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400420 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400422 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400423
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400424 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400425 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200426 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400427
428 In general case you should specify it in the XML-descriptor:
429 <version>
430 VERSION
431 </version>
432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400434 Specify 2nd library version outside the descriptor.
435
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400436 -vnum NUM
437 Specify the library version in the generated ABI dump. The <version> section
438 of the input XML descriptor will be overwritten in this case.
439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400440 -s|-strict
441 Treat all compatibility warnings as problems. Add a number of \"Low\"
442 severity problems to the return value of the tool.
443
444 -headers-only
445 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
446 provide a low quality compatibility report with false positives and
447 without detecting of added/removed symbols.
448
449 Alternatively you can write \"none\" word to the <libs> section
450 in the XML-descriptor:
451 <libs>
452 none
453 </libs>
454
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400455 -show-retval
456 Show the symbol's return type in the report.
457
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400458 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300459 This option allows to specify a file with a list of symbols (mangled
460 names in C++) that should be checked. Other symbols will not be checked.
461
462 -types-list PATH
463 This option allows to specify a file with a list of types that should
464 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400465
466 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300467 The list of symbols that should not be checked.
468
469 -skip-types PATH
470 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400471
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400472 -headers-list PATH
473 The file with a list of headers, that should be checked/dumped.
474
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400475 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400476 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400477
478 -header NAME
479 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400480
481 -use-dumps
482 Make dumps for two versions of a library and compare dumps. This should
483 increase the performance of the tool and decrease the system memory usage.
484
485 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400486 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400487
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400488 -dump-system NAME -sysroot DIR
489 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400490 create XML descriptors and make ABI dumps for each library. The result
491 set of ABI dumps can be compared (--cmp-systems) with the other one
492 created for other version of operating system in order to check them for
493 compatibility. Do not forget to specify -cross-gcc option if your target
494 system requires some specific version of GCC compiler (different from
495 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400496 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400497
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400498 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499 The same as the previous option but takes an XML descriptor of the target
500 system as input, where you should describe it:
501
502 /* Primary sections */
503
504 <name>
505 /* Name of the system */
506 </name>
507
508 <headers>
509 /* The list of paths to header files and/or
510 directories with header files, one per line */
511 </headers>
512
513 <libs>
514 /* The list of paths to shared libraries and/or
515 directories with shared libraries, one per line */
516 </libs>
517
518 /* Optional sections */
519
520 <search_headers>
521 /* List of directories to be searched
522 for header files to automatically
523 generate include paths, one per line */
524 </search_headers>
525
526 <search_libs>
527 /* List of directories to be searched
528 for shared libraries to resolve
529 dependencies, one per line */
530 </search_libs>
531
532 <tools>
533 /* List of directories with tools used
534 for analysis (GCC toolchain), one per line */
535 </tools>
536
537 <cross_prefix>
538 /* GCC toolchain prefix.
539 Examples:
540 arm-linux-gnueabi
541 arm-none-symbianelf */
542 </cross_prefix>
543
544 <gcc_options>
545 /* Additional GCC options, one per line */
546 </gcc_options>
547
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400548 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300549 This option should be used with -dump-system option to dump
550 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400551
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400552 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553 Compare two system ABI dumps. Create compatibility reports for each
554 library and the common HTML report including the summary of test
555 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400556 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400557
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400558 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400559 The file with a list of libraries, that should be dumped by
560 the -dump-system option or should be checked by the -cmp-systems option.
561
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400562 -ext|-extended
563 If your library A is supposed to be used by other library B and you
564 want to control the ABI of B, then you should enable this option. The
565 tool will check for changes in all data types, even if they are not
566 used by any function in the library A. Such data types are not part
567 of the A library ABI, but may be a part of the ABI of the B library.
568
569 The short scheme is:
570 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
571
572 -q|-quiet
573 Print all messages to the file instead of stdout and stderr.
574 Default path (can be changed by -log-path option):
575 $COMMON_LOG_PATH
576
577 -stdout
578 Print analysis results (compatibility reports and ABI dumps) to stdout
579 instead of creating a file. This would allow piping data to other programs.
580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400581 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400582 Change format of compatibility report.
583 Formats:
584 htm - HTML format (default)
585 xml - XML format
586
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400587 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400588 Change format of ABI dump.
589 Formats:
590 perl - Data::Dumper format (default)
591 xml - XML format
592
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400593 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400594 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400595
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400596 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400597 Set library language (C or C++). You can use this option if the tool
598 cannot auto-detect a language. This option may be useful for checking
599 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400600
601 -arch ARCH
602 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
603 ect.). The option is useful if the tool cannot detect correct architecture
604 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400605
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400606 -binary|-bin|-abi
607 Show \"Binary\" compatibility problems only.
608 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400609 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400610
611 -source|-src|-api
612 Show \"Source\" compatibility problems only.
613 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400614 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400615
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400616 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400617 The maximum number of affected symbols listed under the description
618 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300619
620 -count-symbols PATH
621 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300622
623 -old-style
624 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400626OTHER OPTIONS:
627 -test
628 Run internal tests. Create two binary incompatible versions of a sample
629 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300630 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400631
632 -test-dump
633 Test ability to create, read and compare ABI dumps.
634
635 -debug
636 Debugging mode. Print debug info on the screen. Save intermediate
637 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400638 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400639
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400640 Also consider using --dump option for debugging the tool.
641
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400642 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400643 If your header files are written in C language and can be compiled
644 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
645 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400646
647 -cpp-incompatible
648 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400649
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400650 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400651 Path to file with the function parameter names. It can be used
652 for improving report view if the library header files have no
653 parameter names. File format:
654
655 func1;param1;param2;param3 ...
656 func2;param1;param2;param3 ...
657 ...
658
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400659 -relpath PATH
660 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661 for dumping the library ABI (see -dump option).
662
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400663 -relpath1 PATH
664 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400665
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400666 -relpath2 PATH
667 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400668
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400669 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400670 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400671 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400672 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400674 -sort
675 Enable sorting of data in ABI dumps.
676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400678 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400679 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400681
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400682 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400683 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400688 Path to \"Source\" compatibility report.
689 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400691
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693 Log path for all messages.
694 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400698 Log path for 1st version of a library.
699 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400702 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400703 Log path for 2nd version of a library.
704 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400706
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400707 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400708 Change logging mode.
709 Modes:
710 w - overwrite old logs (default)
711 a - append old logs
712 n - do not write any logs
713
714 -list-affected
715 Generate file with the list of incompatible
716 symbols beside the HTML compatibility report.
717 Use 'c++filt \@file' command from GNU binutils
718 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400721 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400722
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724 The component name in the title and summary of the HTML report.
725 Default:
726 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300727
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300728 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400729 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400730 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731
732 -extra-info DIR
733 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400734
735 -extra-dump
736 Create extended ABI dump containing all symbols
737 from the translation unit.
738
739 -force
740 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400741
742 -tolerance LEVEL
743 Apply a set of heuristics to successfully compile input
744 header files. You can enable several tolerance levels by
745 joining them into one string (e.g. 13, 124, etc.).
746 Levels:
747 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
748 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900749 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400750 4 - skip headers included by others
751
752 -tolerant
753 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400754
755 -check
756 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400757
758 -quick
759 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +0300760
761 -disable-quick-empty-report
762 Do not generate quick empty report if input ABI dumps are equal.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400763
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300764 -skip-internal-symbols PATTERN
765 Do not check symbols matched by the pattern.
766
767 -skip-internal-types PATTERN
768 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300769
Andrey Ponomarenko8580e852016-08-19 19:11:48 +0300770 -skip-typedef-uncover
771 Do not report a problem if type is covered or
772 uncovered by typedef (useful for broken debug info).
773
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300774 -check-private-abi
775 Check data types from the private part of the ABI when
776 comparing ABI dumps created by the ABI Dumper tool with
777 use of the -public-headers option.
778
779 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400781REPORT:
782 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400783 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400784
785 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400786 logs/LIB_NAME/V1/log.txt
787 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400788
789EXIT CODES:
790 0 - Compatible. The tool has run without any errors.
791 non-zero - Incompatible or the tool has run with errors.
792
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400793MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300794 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400795}
796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400797my %Operator_Indication = (
798 "not" => "~",
799 "assign" => "=",
800 "andassign" => "&=",
801 "orassign" => "|=",
802 "xorassign" => "^=",
803 "or" => "|",
804 "xor" => "^",
805 "addr" => "&",
806 "and" => "&",
807 "lnot" => "!",
808 "eq" => "==",
809 "ne" => "!=",
810 "lt" => "<",
811 "lshift" => "<<",
812 "lshiftassign" => "<<=",
813 "rshiftassign" => ">>=",
814 "call" => "()",
815 "mod" => "%",
816 "modassign" => "%=",
817 "subs" => "[]",
818 "land" => "&&",
819 "lor" => "||",
820 "rshift" => ">>",
821 "ref" => "->",
822 "le" => "<=",
823 "deref" => "*",
824 "mult" => "*",
825 "preinc" => "++",
826 "delete" => " delete",
827 "vecnew" => " new[]",
828 "vecdelete" => " delete[]",
829 "predec" => "--",
830 "postinc" => "++",
831 "postdec" => "--",
832 "plusassign" => "+=",
833 "plus" => "+",
834 "minus" => "-",
835 "minusassign" => "-=",
836 "gt" => ">",
837 "ge" => ">=",
838 "new" => " new",
839 "multassign" => "*=",
840 "divassign" => "/=",
841 "div" => "/",
842 "neg" => "-",
843 "pos" => "+",
844 "memref" => "->*",
845 "compound" => "," );
846
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400847my %UnknownOperator;
848
849my %NodeType= (
850 "array_type" => "Array",
851 "binfo" => "Other",
852 "boolean_type" => "Intrinsic",
853 "complex_type" => "Intrinsic",
854 "const_decl" => "Other",
855 "enumeral_type" => "Enum",
856 "field_decl" => "Other",
857 "function_decl" => "Other",
858 "function_type" => "FunctionType",
859 "identifier_node" => "Other",
860 "integer_cst" => "Other",
861 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400862 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400863 "method_type" => "MethodType",
864 "namespace_decl" => "Other",
865 "parm_decl" => "Other",
866 "pointer_type" => "Pointer",
867 "real_cst" => "Other",
868 "real_type" => "Intrinsic",
869 "record_type" => "Struct",
870 "reference_type" => "Ref",
871 "string_cst" => "Other",
872 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400873 "template_type_parm" => "TemplateParam",
874 "typename_type" => "TypeName",
875 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400876 "tree_list" => "Other",
877 "tree_vec" => "Other",
878 "type_decl" => "Other",
879 "union_type" => "Union",
880 "var_decl" => "Other",
881 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400882 "nop_expr" => "Other", #
883 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400884 "offset_type" => "Other" );
885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400886my %CppKeywords_C = map {$_=>1} (
887 # C++ 2003 keywords
888 "public",
889 "protected",
890 "private",
891 "default",
892 "template",
893 "new",
894 #"asm",
895 "dynamic_cast",
896 "auto",
897 "try",
898 "namespace",
899 "typename",
900 "using",
901 "reinterpret_cast",
902 "friend",
903 "class",
904 "virtual",
905 "const_cast",
906 "mutable",
907 "static_cast",
908 "export",
909 # C++0x keywords
910 "noexcept",
911 "nullptr",
912 "constexpr",
913 "static_assert",
914 "explicit",
915 # cannot be used as a macro name
916 # as it is an operator in C++
917 "and",
918 #"and_eq",
919 "not",
920 #"not_eq",
921 "or"
922 #"or_eq",
923 #"bitand",
924 #"bitor",
925 #"xor",
926 #"xor_eq",
927 #"compl"
928);
929
930my %CppKeywords_F = map {$_=>1} (
931 "delete",
932 "catch",
933 "alignof",
934 "thread_local",
935 "decltype",
936 "typeid"
937);
938
939my %CppKeywords_O = map {$_=>1} (
940 "bool",
941 "register",
942 "inline",
943 "operator"
944);
945
946my %CppKeywords_A = map {$_=>1} (
947 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400948 "throw",
949 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400950);
951
952foreach (keys(%CppKeywords_C),
953keys(%CppKeywords_F),
954keys(%CppKeywords_O)) {
955 $CppKeywords_A{$_}=1;
956}
957
958# Header file extensions as described by gcc
959my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
960
961my %IntrinsicMangling = (
962 "void" => "v",
963 "bool" => "b",
964 "wchar_t" => "w",
965 "char" => "c",
966 "signed char" => "a",
967 "unsigned char" => "h",
968 "short" => "s",
969 "unsigned short" => "t",
970 "int" => "i",
971 "unsigned int" => "j",
972 "long" => "l",
973 "unsigned long" => "m",
974 "long long" => "x",
975 "__int64" => "x",
976 "unsigned long long" => "y",
977 "__int128" => "n",
978 "unsigned __int128" => "o",
979 "float" => "f",
980 "double" => "d",
981 "long double" => "e",
982 "__float80" => "e",
983 "__float128" => "g",
984 "..." => "z"
985);
986
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400987my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400989my %StdcxxMangling = (
990 "3std"=>"St",
991 "3std9allocator"=>"Sa",
992 "3std12basic_string"=>"Sb",
993 "3std12basic_stringIcE"=>"Ss",
994 "3std13basic_istreamIcE"=>"Si",
995 "3std13basic_ostreamIcE"=>"So",
996 "3std14basic_iostreamIcE"=>"Sd"
997);
998
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400999my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001000my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1001
1002my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001003my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001005my %ConstantSuffix = (
1006 "unsigned int"=>"u",
1007 "long"=>"l",
1008 "unsigned long"=>"ul",
1009 "long long"=>"ll",
1010 "unsigned long long"=>"ull"
1011);
1012
1013my %ConstantSuffixR =
1014reverse(%ConstantSuffix);
1015
1016my %OperatorMangling = (
1017 "~" => "co",
1018 "=" => "aS",
1019 "|" => "or",
1020 "^" => "eo",
1021 "&" => "an",#ad (addr)
1022 "==" => "eq",
1023 "!" => "nt",
1024 "!=" => "ne",
1025 "<" => "lt",
1026 "<=" => "le",
1027 "<<" => "ls",
1028 "<<=" => "lS",
1029 ">" => "gt",
1030 ">=" => "ge",
1031 ">>" => "rs",
1032 ">>=" => "rS",
1033 "()" => "cl",
1034 "%" => "rm",
1035 "[]" => "ix",
1036 "&&" => "aa",
1037 "||" => "oo",
1038 "*" => "ml",#de (deref)
1039 "++" => "pp",#
1040 "--" => "mm",#
1041 "new" => "nw",
1042 "delete" => "dl",
1043 "new[]" => "na",
1044 "delete[]" => "da",
1045 "+=" => "pL",
1046 "+" => "pl",#ps (pos)
1047 "-" => "mi",#ng (neg)
1048 "-=" => "mI",
1049 "*=" => "mL",
1050 "/=" => "dV",
1051 "&=" => "aN",
1052 "|=" => "oR",
1053 "%=" => "rM",
1054 "^=" => "eO",
1055 "/" => "dv",
1056 "->*" => "pm",
1057 "->" => "pt",#rf (ref)
1058 "," => "cm",
1059 "?" => "qu",
1060 "." => "dt",
1061 "sizeof"=> "sz"#st
1062);
1063
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001064my %Intrinsic_Keywords = map {$_=>1} (
1065 "true",
1066 "false",
1067 "_Bool",
1068 "_Complex",
1069 "const",
1070 "int",
1071 "long",
1072 "void",
1073 "short",
1074 "float",
1075 "volatile",
1076 "restrict",
1077 "unsigned",
1078 "signed",
1079 "char",
1080 "double",
1081 "class",
1082 "struct",
1083 "union",
1084 "enum"
1085);
1086
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001087my %GlibcHeader = map {$_=>1} (
1088 "aliases.h",
1089 "argp.h",
1090 "argz.h",
1091 "assert.h",
1092 "cpio.h",
1093 "ctype.h",
1094 "dirent.h",
1095 "envz.h",
1096 "errno.h",
1097 "error.h",
1098 "execinfo.h",
1099 "fcntl.h",
1100 "fstab.h",
1101 "ftw.h",
1102 "glob.h",
1103 "grp.h",
1104 "iconv.h",
1105 "ifaddrs.h",
1106 "inttypes.h",
1107 "langinfo.h",
1108 "limits.h",
1109 "link.h",
1110 "locale.h",
1111 "malloc.h",
1112 "math.h",
1113 "mntent.h",
1114 "monetary.h",
1115 "nl_types.h",
1116 "obstack.h",
1117 "printf.h",
1118 "pwd.h",
1119 "regex.h",
1120 "sched.h",
1121 "search.h",
1122 "setjmp.h",
1123 "shadow.h",
1124 "signal.h",
1125 "spawn.h",
1126 "stdarg.h",
1127 "stdint.h",
1128 "stdio.h",
1129 "stdlib.h",
1130 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001131 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001132 "tar.h",
1133 "termios.h",
1134 "time.h",
1135 "ulimit.h",
1136 "unistd.h",
1137 "utime.h",
1138 "wchar.h",
1139 "wctype.h",
1140 "wordexp.h" );
1141
1142my %GlibcDir = map {$_=>1} (
1143 "arpa",
1144 "bits",
1145 "gnu",
1146 "netinet",
1147 "net",
1148 "nfs",
1149 "rpc",
1150 "sys",
1151 "linux" );
1152
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001153my %WinHeaders = map {$_=>1} (
1154 "dos.h",
1155 "process.h",
1156 "winsock.h",
1157 "config-win.h",
1158 "mem.h",
1159 "windows.h",
1160 "winsock2.h",
1161 "crtdbg.h",
1162 "ws2tcpip.h"
1163);
1164
1165my %ObsoleteHeaders = map {$_=>1} (
1166 "iostream.h",
1167 "fstream.h"
1168);
1169
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001170my %AlienHeaders = map {$_=>1} (
1171 # Solaris
1172 "thread.h",
1173 "sys/atomic.h",
1174 # HPUX
1175 "sys/stream.h",
1176 # Symbian
1177 "AknDoc.h",
1178 # Atari ST
1179 "ext.h",
1180 "tos.h",
1181 # MS-DOS
1182 "alloc.h",
1183 # Sparc
1184 "sys/atomic.h"
1185);
1186
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001187my %ConfHeaders = map {$_=>1} (
1188 "atomic",
1189 "conf.h",
1190 "config.h",
1191 "configure.h",
1192 "build.h",
1193 "setup.h"
1194);
1195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001196my %LocalIncludes = map {$_=>1} (
1197 "/usr/local/include",
1198 "/usr/local" );
1199
1200my %OS_AddPath=(
1201# These paths are needed if the tool cannot detect them automatically
1202 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001203 "include"=>[
1204 "/Library",
1205 "/Developer/usr/include"
1206 ],
1207 "lib"=>[
1208 "/Library",
1209 "/Developer/usr/lib"
1210 ],
1211 "bin"=>[
1212 "/Developer/usr/bin"
1213 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001214 },
1215 "beos"=>{
1216 # Haiku has GCC 2.95.3 by default
1217 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001218 "include"=>[
1219 "/boot/common",
1220 "/boot/develop"
1221 ],
1222 "lib"=>[
1223 "/boot/common/lib",
1224 "/boot/system/lib",
1225 "/boot/apps"
1226 ],
1227 "bin"=>[
1228 "/boot/common/bin",
1229 "/boot/system/bin",
1230 "/boot/develop/abi"
1231 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001233);
1234
1235my %Slash_Type=(
1236 "default"=>"/",
1237 "windows"=>"\\"
1238);
1239
1240my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1241
1242# Global Variables
1243my %COMMON_LANGUAGE=(
1244 1 => "C",
1245 2 => "C" );
1246
1247my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001248my $MAX_CPPFILT_FILE_SIZE = 50000;
1249my $CPPFILT_SUPPORT_FILE;
1250
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001251my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1252
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001253my $STDCXX_TESTING = 0;
1254my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001255my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001256
1257my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001258my $CheckUndefined = 0;
1259
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001260my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001261if($TargetComponent_Opt) {
1262 $TargetComponent = lc($TargetComponent_Opt);
1263}
1264else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001265{ # default: library
1266 # other components: header, system, ...
1267 $TargetComponent = "library";
1268}
1269
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001270my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001272my $SystemRoot;
1273
1274my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001275my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001276my %LOG_PATH;
1277my %DEBUG_PATH;
1278my %Cache;
1279my %LibInfo;
1280my $COMPILE_ERRORS = 0;
1281my %CompilerOptions;
1282my %CheckedDyLib;
1283my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1284
1285# Constants (#defines)
1286my %Constants;
1287my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001288my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001289
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001290# Extra Info
1291my %SymbolHeader;
1292my %KnownLibs;
1293
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001294# Templates
1295my %TemplateInstance;
1296my %BasicTemplate;
1297my %TemplateArg;
1298my %TemplateDecl;
1299my %TemplateMap;
1300
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001301# Types
1302my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001303my %SkipTypes = (
1304 "1"=>{},
1305 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001306my %CheckedTypes;
1307my %TName_Tid;
1308my %EnumMembName_Id;
1309my %NestedNameSpaces = (
1310 "1"=>{},
1311 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001312my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001313my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001314my %ClassVTable;
1315my %ClassVTable_Content;
1316my %VTableClass;
1317my %AllocableClass;
1318my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001319my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001320my %Class_SubClasses;
1321my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001322my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001323my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001325my %CheckedTypeInfo;
1326
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001327# Typedefs
1328my %Typedef_BaseName;
1329my %Typedef_Tr;
1330my %Typedef_Eq;
1331my %StdCxxTypedef;
1332my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001333my %MissedBase;
1334my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001335my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336
1337# Symbols
1338my %SymbolInfo;
1339my %tr_name;
1340my %mangled_name_gcc;
1341my %mangled_name;
1342my %SkipSymbols = (
1343 "1"=>{},
1344 "2"=>{} );
1345my %SkipNameSpaces = (
1346 "1"=>{},
1347 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001348my %AddNameSpaces = (
1349 "1"=>{},
1350 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001352my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001353my %SymbolsList_App;
1354my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001355my %Symbol_Library = (
1356 "1"=>{},
1357 "2"=>{} );
1358my %Library_Symbol = (
1359 "1"=>{},
1360 "2"=>{} );
1361my %DepSymbol_Library = (
1362 "1"=>{},
1363 "2"=>{} );
1364my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001365 "1"=>{},
1366 "2"=>{} );
1367my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001368my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001370my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001371my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001372my %Library_Needed= (
1373 "1"=>{},
1374 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001375
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001376# Extra Info
1377my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001378my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001381my %Include_Preamble = (
1382 "1"=>[],
1383 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001385my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386my %HeaderName_Paths;
1387my %Header_Dependency;
1388my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001389my %Include_Paths = (
1390 "1"=>[],
1391 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001392my %INC_PATH_AUTODETECT = (
1393 "1"=>1,
1394 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001395my %Add_Include_Paths = (
1396 "1"=>[],
1397 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398my %Skip_Include_Paths;
1399my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400my %Header_ErrorRedirect;
1401my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001402my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001403my %Header_ShouldNotBeUsed;
1404my %RecursiveIncludes;
1405my %Header_Include_Prefix;
1406my %SkipHeaders;
1407my %SkipHeadersList=(
1408 "1"=>{},
1409 "2"=>{} );
1410my %SkipLibs;
1411my %Include_Order;
1412my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001413my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001414my %TUnit_Funcs;
1415my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001417my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418 "1"=>0,
1419 "2"=>0 );
1420my %AutoPreambleMode = (
1421 "1"=>0,
1422 "2"=>0 );
1423my %MinGWMode = (
1424 "1"=>0,
1425 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001426my %Cpp0xMode = (
1427 "1"=>0,
1428 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001429
1430# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001431my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001432my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001433my %RegisteredSONAMEs;
1434my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001435
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001436my %CheckedArch;
1437
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438# System Objects
1439my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001440my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001441my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001442
1443# System Headers
1444my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001445my @DefaultCppPaths;
1446my @DefaultGccPaths;
1447my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001448my %DefaultCppHeader;
1449my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001450my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001451
1452# Merging
1453my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454my $Version;
1455my %AddedInt;
1456my %RemovedInt;
1457my %AddedInt_Virt;
1458my %RemovedInt_Virt;
1459my %VirtualReplacement;
1460my %ChangedTypedef;
1461my %CompatRules;
1462my %IncompleteRules;
1463my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001464my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001465my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001466my %ReturnedClass;
1467my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001468my %SourceAlternative;
1469my %SourceAlternative_B;
1470my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001471my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001472
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001473#Report
1474my %TypeChanges;
1475
1476#Speedup
1477my %TypeProblemsIndex;
1478
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001479# Calling Conventions
1480my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001481 1=>{ "R"=>0, "P"=>0 },
1482 2=>{ "R"=>0, "P"=>0 }
1483);
1484
1485# ABI Dump
1486my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001487
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001488# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001489my %TargetLibs;
1490my %TargetHeaders;
1491
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001492# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001493my $OStarget = $OSgroup;
1494my %TargetTools;
1495
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001496# Recursion locks
1497my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001498my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001499my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001500my @RecurInclude;
1501my @RecurConstant;
1502
1503# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001504my %SystemPaths = (
1505 "include"=>[],
1506 "lib"=>[],
1507 "bin"=>[]
1508);
1509my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001510my $GCC_PATH;
1511
1512# Symbols versioning
1513my %SymVer = (
1514 "1"=>{},
1515 "2"=>{} );
1516
1517# Problem descriptions
1518my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001519my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001520my %TotalAffected;
1521
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001522# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001523my $ContentID = 1;
1524my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001525my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1526my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001527my $ContentSpanEnd = "</span>\n";
1528my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1529my $ContentDivEnd = "</div>\n";
1530my $Content_Counter = 0;
1531
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001532# Modes
1533my $JoinReport = 1;
1534my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001535
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001536my %Severity_Val=(
1537 "High"=>3,
1538 "Medium"=>2,
1539 "Low"=>1,
1540 "Safe"=>-1
1541);
1542
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001543sub get_Modules()
1544{
1545 my $TOOL_DIR = get_dirname($0);
1546 if(not $TOOL_DIR)
1547 { # patch for MS Windows
1548 $TOOL_DIR = ".";
1549 }
1550 my @SEARCH_DIRS = (
1551 # tool's directory
1552 abs_path($TOOL_DIR),
1553 # relative path to modules
1554 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001555 # install path
1556 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001557 );
1558 foreach my $DIR (@SEARCH_DIRS)
1559 {
1560 if(not is_abs($DIR))
1561 { # relative path
1562 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1563 }
1564 if(-d $DIR."/modules") {
1565 return $DIR."/modules";
1566 }
1567 }
1568 exitStatus("Module_Error", "can't find modules");
1569}
1570
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001571my %LoadedModules = ();
1572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001573sub loadModule($)
1574{
1575 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001576 if(defined $LoadedModules{$Name}) {
1577 return;
1578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1580 if(not -f $Path) {
1581 exitStatus("Module_Error", "can't access \'$Path\'");
1582 }
1583 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001584 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001585}
1586
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001587sub readModule($$)
1588{
1589 my ($Module, $Name) = @_;
1590 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1591 if(not -f $Path) {
1592 exitStatus("Module_Error", "can't access \'$Path\'");
1593 }
1594 return readFile($Path);
1595}
1596
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001597sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001598{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001599 my $Number = $_[0];
1600 if(not $Number) {
1601 $Number = 1;
1602 }
1603 else {
1604 $Number = int($Number)+1;
1605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001606 if($Number>3) {
1607 return $Number."th";
1608 }
1609 elsif($Number==1) {
1610 return "1st";
1611 }
1612 elsif($Number==2) {
1613 return "2nd";
1614 }
1615 elsif($Number==3) {
1616 return "3rd";
1617 }
1618 else {
1619 return $Number;
1620 }
1621}
1622
1623sub search_Tools($)
1624{
1625 my $Name = $_[0];
1626 return "" if(not $Name);
1627 if(my @Paths = keys(%TargetTools))
1628 {
1629 foreach my $Path (@Paths)
1630 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001631 if(-f join_P($Path, $Name)) {
1632 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001633 }
1634 if($CrossPrefix)
1635 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001636 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001637 if(-f $Candidate) {
1638 return $Candidate;
1639 }
1640 }
1641 }
1642 }
1643 else {
1644 return "";
1645 }
1646}
1647
1648sub synch_Cmd($)
1649{
1650 my $Name = $_[0];
1651 if(not $GCC_PATH)
1652 { # GCC was not found yet
1653 return "";
1654 }
1655 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001656 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001657 return $Candidate;
1658 }
1659 return "";
1660}
1661
1662sub get_CmdPath($)
1663{
1664 my $Name = $_[0];
1665 return "" if(not $Name);
1666 if(defined $Cache{"get_CmdPath"}{$Name}) {
1667 return $Cache{"get_CmdPath"}{$Name};
1668 }
1669 my %BinUtils = map {$_=>1} (
1670 "c++filt",
1671 "objdump",
1672 "readelf"
1673 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001674 if($BinUtils{$Name} and $GCC_PATH)
1675 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001676 if(my $Dir = get_dirname($GCC_PATH)) {
1677 $TargetTools{$Dir}=1;
1678 }
1679 }
1680 my $Path = search_Tools($Name);
1681 if(not $Path and $OSgroup eq "windows") {
1682 $Path = search_Tools($Name.".exe");
1683 }
1684 if(not $Path and $BinUtils{$Name})
1685 {
1686 if($CrossPrefix)
1687 { # user-defined prefix
1688 $Path = search_Cmd($CrossPrefix."-".$Name);
1689 }
1690 }
1691 if(not $Path and $BinUtils{$Name})
1692 {
1693 if(my $Candidate = synch_Cmd($Name))
1694 { # synch with GCC
1695 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001696 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001697 if(-f $Candidate) {
1698 $Path = $Candidate;
1699 }
1700 }
1701 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001702 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001703 $Path = $Candidate;
1704 }
1705 }
1706 }
1707 if(not $Path) {
1708 $Path = search_Cmd($Name);
1709 }
1710 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001711 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 $Path=search_Cmd($Name.".exe");
1713 }
1714 if($Path=~/\s/) {
1715 $Path = "\"".$Path."\"";
1716 }
1717 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1718}
1719
1720sub search_Cmd($)
1721{
1722 my $Name = $_[0];
1723 return "" if(not $Name);
1724 if(defined $Cache{"search_Cmd"}{$Name}) {
1725 return $Cache{"search_Cmd"}{$Name};
1726 }
1727 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1728 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1729 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001730 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001731 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001732 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733 if(-f $CmdPath)
1734 {
1735 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001737 }
1738 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1739 }
1740 }
1741 return ($Cache{"search_Cmd"}{$Name} = "");
1742}
1743
1744sub get_CmdPath_Default($)
1745{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001746 return "" if(not $_[0]);
1747 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1748 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001749 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001750 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1751}
1752
1753sub get_CmdPath_Default_I($)
1754{ # search in PATH
1755 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001756 if($Name=~/find/)
1757 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001758 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001759 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001760 }
1761 }
1762 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001763 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001764 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001765 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001766 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001768 if($OSgroup eq "windows")
1769 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001770 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001771 return $Name;
1772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001773 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001774 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001775 {
1776 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001777 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001778 }
1779 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001780 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001781}
1782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001783sub classifyPath($)
1784{
1785 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001786 if($Path=~/[\*\+\(\[\|]/)
1787 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001788 return ($Path, "Pattern");
1789 }
1790 elsif($Path=~/[\/\\]/)
1791 { # directory or relative path
1792 return (path_format($Path, $OSgroup), "Path");
1793 }
1794 else {
1795 return ($Path, "Name");
1796 }
1797}
1798
1799sub readDescriptor($$)
1800{
1801 my ($LibVersion, $Content) = @_;
1802 return if(not $LibVersion);
1803 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1804 if(not $Content) {
1805 exitStatus("Error", "$DName is empty");
1806 }
1807 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001808 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001809 }
1810 $Content=~s/\/\*(.|\n)+?\*\///g;
1811 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001813 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1814 if($TargetVersion{$LibVersion}) {
1815 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1816 }
1817 if(not $Descriptor{$LibVersion}{"Version"}) {
1818 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1819 }
1820 if($Content=~/{RELPATH}/)
1821 {
1822 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1823 $Content =~ s/{RELPATH}/$RelDir/g;
1824 }
1825 else
1826 {
1827 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1828 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1829 }
1830 }
1831
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001832 my $DHeaders = parseTag(\$Content, "headers");
1833 if(not $DHeaders) {
1834 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1835 }
1836 elsif(lc($DHeaders) ne "none")
1837 { # append the descriptor headers list
1838 if($Descriptor{$LibVersion}{"Headers"})
1839 { # multiple descriptors
1840 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001841 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001842 else {
1843 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1844 }
1845 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1846 {
1847 if(not -e $Path) {
1848 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001849 }
1850 }
1851 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001852
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001853 if(not $CheckHeadersOnly_Opt)
1854 {
1855 my $DObjects = parseTag(\$Content, "libs");
1856 if(not $DObjects) {
1857 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1858 }
1859 elsif(lc($DObjects) ne "none")
1860 { # append the descriptor libraries list
1861 if($Descriptor{$LibVersion}{"Libs"})
1862 { # multiple descriptors
1863 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1864 }
1865 else {
1866 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1867 }
1868 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1869 {
1870 if(not -e $Path) {
1871 exitStatus("Access_Error", "can't access \'$Path\'");
1872 }
1873 }
1874 }
1875 }
1876 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1877 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001878 if(not -d $Path) {
1879 exitStatus("Access_Error", "can't access directory \'$Path\'");
1880 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001881 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001882 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001883 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001884 }
1885 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1886 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 if(not -d $Path) {
1888 exitStatus("Access_Error", "can't access directory \'$Path\'");
1889 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001890 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001891 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001892 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 }
1894 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1895 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 if(not -d $Path) {
1897 exitStatus("Access_Error", "can't access directory \'$Path\'");
1898 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001899 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001900 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001901 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001902 $TargetTools{$Path}=1;
1903 }
1904 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1905 $CrossPrefix = $Prefix;
1906 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001907 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001908 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1909 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001910 if(not -d $Path) {
1911 exitStatus("Access_Error", "can't access directory \'$Path\'");
1912 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001913 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001915 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001917 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001918 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1919 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 if(not -d $Path) {
1921 exitStatus("Access_Error", "can't access directory \'$Path\'");
1922 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001923 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001924 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001925 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 }
1927 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001928 { # skip some auto-generated include paths
1929 if(not is_abs($Path))
1930 {
1931 if(my $P = abs_path($Path)) {
1932 $Path = $P;
1933 }
1934 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001935 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 }
1937 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001938 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001939 my ($CPath, $Type) = classifyPath($Path);
1940 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001941 }
1942 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001943 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1944 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001945 if($Option!~/\A\-(Wl|l|L)/)
1946 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001947 $CompilerOptions{$LibVersion} .= " ".$Option;
1948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001949 }
1950 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1951 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1952 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001953 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001955 my ($CPath, $Type) = classifyPath($Path);
1956 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001957 }
1958 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1959 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1960 {
1961 my ($CPath, $Type) = classifyPath($Path);
1962 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1963 }
1964 if(my $DDefines = parseTag(\$Content, "defines"))
1965 {
1966 if($Descriptor{$LibVersion}{"Defines"})
1967 { # multiple descriptors
1968 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1969 }
1970 else {
1971 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1972 }
1973 }
1974 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1975 {
1976 if($Order=~/\A(.+):(.+)\Z/) {
1977 $Include_Order{$LibVersion}{$1} = $2;
1978 }
1979 }
1980 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1981 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001982 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001983 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1984 }
1985 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1986 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001987 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001988 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1989 }
1990 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1991 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1992 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001993 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1994 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001996 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1997 $SkipConstants{$LibVersion}{$Constant} = 1;
1998 }
1999 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2000 {
2001 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002002 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002003 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2004 }
2005 else {
2006 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2007 }
2008 }
2009}
2010
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002011sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002012{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002013 my $CodeRef = shift(@_);
2014 my $Tag = shift(@_);
2015 if(not $Tag or not $CodeRef) {
2016 return undef;
2017 }
2018 my $Sp = 0;
2019 if(@_) {
2020 $Sp = shift(@_);
2021 }
2022 my $Start = index(${$CodeRef}, "<$Tag>");
2023 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002025 my $End = index(${$CodeRef}, "</$Tag>");
2026 if($End!=-1)
2027 {
2028 my $TS = length($Tag)+3;
2029 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2030 substr($Content, 0, $TS-1, ""); # cut start tag
2031 substr($Content, -$TS, $TS, ""); # cut end tag
2032 if(not $Sp)
2033 {
2034 $Content=~s/\A\s+//g;
2035 $Content=~s/\s+\Z//g;
2036 }
2037 if(substr($Content, 0, 1) ne "<") {
2038 $Content = xmlSpecChars_R($Content);
2039 }
2040 return $Content;
2041 }
2042 }
2043 return undef;
2044}
2045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002046sub getInfo($)
2047{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002048 my $DumpPath = $_[0];
2049 return if(not $DumpPath or not -f $DumpPath);
2050
2051 readTUDump($DumpPath);
2052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002053 # processing info
2054 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002055
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002056 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002057 setAnonTypedef_All();
2058 }
2059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 getTypeInfo_All();
2061 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002062 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002063 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002064 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002065
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002066 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002067 %LibInfo = ();
2068 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002069 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002070 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002071 %TemplateDecl = ();
2072 %StdCxxTypedef = ();
2073 %MissedTypedef = ();
2074 %Typedef_Tr = ();
2075 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002076 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002077
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002078 # clean cache
2079 delete($Cache{"getTypeAttr"});
2080 delete($Cache{"getTypeDeclId"});
2081
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002082 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002083 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002084 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002085 }
2086 else
2087 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002088 if($BinaryOnly and not $ExtendedCheck)
2089 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002090 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002091 }
2092 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002093 remove_Unused($Version, "Extended");
2094 }
2095 }
2096
2097 if($CheckInfo)
2098 {
2099 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2100 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2101 }
2102
2103 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2104 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002106 }
2107
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002108 if($Debug) {
2109 # debugMangling($Version);
2110 }
2111}
2112
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113sub readTUDump($)
2114{
2115 my $DumpPath = $_[0];
2116
2117 open(TU_DUMP, $DumpPath);
2118 local $/ = undef;
2119 my $Content = <TU_DUMP>;
2120 close(TU_DUMP);
2121
2122 unlink($DumpPath);
2123
2124 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002125 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002126
2127 # clean memory
2128 undef $Content;
2129
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002130 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002131
2132 foreach (0 .. $#Lines)
2133 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002134 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002135 { # get a number and attributes of a node
2136 next if(not $NodeType{$2});
2137 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002138 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002139 }
2140
2141 # clean memory
2142 delete($Lines[$_]);
2143 }
2144
2145 # clean memory
2146 undef @Lines;
2147}
2148
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002149sub simplifyConstants()
2150{
2151 foreach my $Constant (keys(%{$Constants{$Version}}))
2152 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002153 if(defined $Constants{$Version}{$Constant}{"Header"})
2154 {
2155 my $Value = $Constants{$Version}{$Constant}{"Value"};
2156 if(defined $EnumConstants{$Version}{$Value}) {
2157 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2158 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002159 }
2160 }
2161}
2162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002163sub simplifyNames()
2164{
2165 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2166 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002167 if($Typedef_Eq{$Version}{$Base}) {
2168 next;
2169 }
2170 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2171 if($#Translations==0)
2172 {
2173 if(length($Translations[0])<=length($Base)) {
2174 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2175 }
2176 }
2177 else
2178 { # select most appropriate
2179 foreach my $Tr (@Translations)
2180 {
2181 if($Base=~/\A\Q$Tr\E/)
2182 {
2183 $Typedef_Eq{$Version}{$Base} = $Tr;
2184 last;
2185 }
2186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002187 }
2188 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002189 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002190 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002191 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002192 if(not $TypeName) {
2193 next;
2194 }
2195 next if(index($TypeName,"<")==-1);# template instances only
2196 if($TypeName=~/>(::\w+)+\Z/)
2197 { # skip unused types
2198 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002199 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002200 foreach my $Base (sort {length($b)<=>length($a)}
2201 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002202 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002203 next if(not $Base);
2204 next if(index($TypeName,$Base)==-1);
2205 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002206 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002207 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002208 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2209 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2210 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002211 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002212 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2213 {
2214 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2215 {
2216 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2217 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002218 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002219 }
2220 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002223 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002224 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002225 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2226 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002227 }
2228}
2229
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002230sub setAnonTypedef_All()
2231{
2232 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2233 {
2234 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2235 {
2236 if(isAnon(getNameByInfo($InfoId))) {
2237 $TypedefToAnon{getTypeId($InfoId)} = 1;
2238 }
2239 }
2240 }
2241}
2242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002243sub setTemplateParams_All()
2244{
2245 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2246 {
2247 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2248 setTemplateParams($_);
2249 }
2250 }
2251}
2252
2253sub setTemplateParams($)
2254{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002255 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002256 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002257 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002258 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002259 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002260 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002261 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002262 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002263 setTemplateInstParams($_[0], $TmplInst_Id);
2264 }
2265 }
2266
2267 $BasicTemplate{$Version}{$Tid} = $_[0];
2268
2269 if(my $Prms = getTreeAttr_Prms($_[0]))
2270 {
2271 if(my $Valu = getTreeAttr_Valu($Prms))
2272 {
2273 my $Vector = getTreeVec($Valu);
2274 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2275 {
2276 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2277 {
2278 if(my $Name = getNameByInfo($Val))
2279 {
2280 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2281 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2282 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2283 }
2284 else {
2285 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2286 }
2287 }
2288 }
2289 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002291 }
2292 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002293 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002294 {
2295 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2296 {
2297 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002298 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002299 }
2300 }
2301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002302}
2303
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002304sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002305{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002306 my ($Tmpl, $Inst) = @_;
2307
2308 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002309 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002310 my ($Params_InfoId, $ElemId) = ();
2311 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2312 $Params_InfoId = $1;
2313 }
2314 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2315 $ElemId = $1;
2316 }
2317 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002318 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002319 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2320 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2321 {
2322 my ($PPos, $PTypeId) = ($1, $2);
2323 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2324 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002325 if($PType eq "template_type_parm") {
2326 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002327 }
2328 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002329 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2330 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002331 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002332 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002333 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002334 else
2335 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002336 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002337 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339 }
2340 }
2341 }
2342}
2343
2344sub getTypeDeclId($)
2345{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002346 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002347 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002348 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2349 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2350 }
2351 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2352 {
2353 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2354 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2355 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002358 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002359}
2360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002361sub getTypeInfo_All()
2362{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002363 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002364 { # support for GCC < 4.5
2365 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2366 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2367 # FIXME: check GCC versions
2368 addMissedTypes_Pre();
2369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002371 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002372 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002373 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2374 if($IType=~/_type\Z/ and $IType ne "function_type"
2375 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002376 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002377 }
2378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002379
2380 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002381 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002382 "Name" => "...",
2383 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002384 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002385 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002386 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002387
2388 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002389 { # support for GCC < 4.5
2390 addMissedTypes_Post();
2391 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002392
2393 if($ADD_TMPL_INSTANCES)
2394 {
2395 # templates
2396 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2397 {
2398 if(defined $TemplateMap{$Version}{$Tid}
2399 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2400 {
2401 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2402 {
2403 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2404 {
2405 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2406 {
2407 if(my %MAttr = getTypeAttr($MembTypeId))
2408 {
2409 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2410 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2411 }
2412 }
2413 }
2414 }
2415 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2416 {
2417 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2418 {
2419 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2420
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002421 if($NBid ne $Bid
2422 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002423 {
2424 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2425 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2426 }
2427 }
2428 }
2429 }
2430 }
2431 }
2432}
2433
2434sub createType($$)
2435{
2436 my ($Attr, $LibVersion) = @_;
2437 my $NewId = ++$MAX_ID;
2438
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002439 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002440 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002441 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002442
2443 return "$NewId";
2444}
2445
2446sub instType($$$)
2447{ # create template instances
2448 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002449
2450 if(not $TypeInfo{$LibVersion}{$Tid}) {
2451 return undef;
2452 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002453 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2454
2455 foreach my $Key (sort keys(%{$Map}))
2456 {
2457 if(my $Val = $Map->{$Key})
2458 {
2459 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2460
2461 if(defined $Attr->{"NameSpace"}) {
2462 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2463 }
2464 foreach (keys(%{$Attr->{"TParam"}})) {
2465 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2466 }
2467 }
2468 else
2469 { # remove absent
2470 # _Traits, etc.
2471 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002472 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002473 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2474 }
2475 foreach (keys(%{$Attr->{"TParam"}}))
2476 {
2477 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2478 delete($Attr->{"TParam"}{$_});
2479 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002480 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002481 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2482 }
2483 }
2484 }
2485 }
2486
2487 my $Tmpl = 0;
2488
2489 if(defined $Attr->{"TParam"})
2490 {
2491 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2492 {
2493 my $PName = $Attr->{"TParam"}{$_}{"name"};
2494
2495 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2496 {
2497 my %Base = get_BaseType($PTid, $LibVersion);
2498
2499 if($Base{"Type"} eq "TemplateParam"
2500 or defined $Base{"Template"})
2501 {
2502 $Tmpl = 1;
2503 last
2504 }
2505 }
2506 }
2507 }
2508
2509 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2510 return "$Id";
2511 }
2512 else
2513 {
2514 if(not $Tmpl) {
2515 delete($Attr->{"Template"});
2516 }
2517
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002518 my $New = createType($Attr, $LibVersion);
2519
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002520 my %EMap = ();
2521 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2522 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2523 }
2524 foreach (keys(%{$Map})) {
2525 $EMap{$_} = $Map->{$_};
2526 }
2527
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2529 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002530 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002531 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002532 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002533 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002534 {
2535 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2536
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002537 if($NBid ne $Bid
2538 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002539 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002540 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2541 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002542 }
2543 }
2544 }
2545
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002546 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002547 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002548 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2549 {
2550 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2551 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2552 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002553 }
2554 }
2555
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002556 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002557 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002558 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2559 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002560 }
2561 }
2562
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002563 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2564 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002565 }
2566
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002567 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002569}
2570
2571sub addMissedTypes_Pre()
2572{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002573 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002574 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2575 { # detecting missed typedefs
2576 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2577 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002578 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002579 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002580 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 if($TypeType eq "Unknown")
2582 { # template_type_parm
2583 next;
2584 }
2585 my $TypeDeclId = getTypeDeclId($TypeId);
2586 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2587 my $TypedefName = getNameByInfo($MissedTDid);
2588 next if(not $TypedefName);
2589 next if($TypedefName eq "__float80");
2590 next if(isAnon($TypedefName));
2591 if(not $TypeDeclId
2592 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002593 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002594 }
2595 }
2596 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002597 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002598 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002599 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002600 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002601 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 next;
2603 }
2604 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002606 if(not $TypedefName) {
2607 next;
2608 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002609 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 my %MissedInfo = ( # typedef info
2611 "Name" => $TypedefName,
2612 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002613 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002615 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 my ($H, $L) = getLocation($MissedTDid);
2617 $MissedInfo{"Header"} = $H;
2618 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002619 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 { # other types
2621 next;
2622 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002623 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002624 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 next;
2626 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002627 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002628 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002629 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002631 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002632 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002633 next;
2634 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002635 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002636 next;
2637 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002638 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002640 next;
2641 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002642 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002643 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002644 next;
2645 }
2646 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002647
2648 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2649
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002651 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002652 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002653 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655
2656 # add missed & remove other
2657 $TypeInfo{$Version} = \%AddTypes;
2658 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002659}
2660
2661sub addMissedTypes_Post()
2662{
2663 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2664 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002665 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2666 {
2667 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2668 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2669 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2670 }
2671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 }
2673}
2674
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002675sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002676{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002677 my $TypeId = $_[0];
2678 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2679 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002681 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683}
2684
2685sub getArraySize($$)
2686{
2687 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 if(my $Size = getSize($TypeId))
2689 {
2690 my $Elems = $Size/$BYTE_SIZE;
2691 while($BaseName=~s/\s*\[(\d+)\]//) {
2692 $Elems/=$1;
2693 }
2694 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2695 {
2696 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2697 $Elems/=$BasicSize;
2698 }
2699 }
2700 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002701 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002702 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002703}
2704
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002705sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002706{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002707 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002709 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2710 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002711 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002712 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2713 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2714 if(not $NodeType)
2715 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 return ();
2717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002718 if($NodeType eq "tree_vec")
2719 {
2720 if($Pos!=$#Positions)
2721 { # select last vector of parameters ( ns<P1>::type<P2> )
2722 next;
2723 }
2724 }
2725 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2726 foreach my $P (@Params)
2727 {
2728 if($P eq "") {
2729 return ();
2730 }
2731 elsif($P ne "\@skip\@") {
2732 @TmplParams = (@TmplParams, $P);
2733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 }
2735 }
2736 return @TmplParams;
2737}
2738
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002739sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002742 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 if(defined $TypeInfo{$Version}{$TypeId}
2744 and $TypeInfo{$Version}{$TypeId}{"Name"})
2745 { # already created
2746 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2749 { # incomplete type
2750 return ();
2751 }
2752 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2753
2754 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002756
2757 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2758 {
2759 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2760 {
2761 if($Info=~/qual[ ]*:/)
2762 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002763 my $NewId = ++$MAX_ID;
2764
2765 $MissedBase{$Version}{$TypeId} = "$NewId";
2766 $MissedBase_R{$Version}{$NewId} = $TypeId;
2767 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2768 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002769 }
2770 }
2771 $TypeAttr{"Type"} = "Typedef";
2772 }
2773 else {
2774 $TypeAttr{"Type"} = getTypeType($TypeId);
2775 }
2776
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002777 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2778 {
2779 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2780 { # local code
2781 return ();
2782 }
2783 }
2784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002785 if($TypeAttr{"Type"} eq "Unknown") {
2786 return ();
2787 }
2788 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2789 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002790 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002791 if(my $TName = $TypeAttr{"Name"})
2792 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002793 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002794 $TName_Tid{$Version}{$TName} = $TypeId;
2795 return %TypeAttr;
2796 }
2797 else {
2798 return ();
2799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002800 }
2801 elsif($TypeAttr{"Type"} eq "Array")
2802 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002803 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2804 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002805 return ();
2806 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002807 if(my $Algn = getAlgn($TypeId)) {
2808 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2809 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002810 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002811 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002812 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002813 if(not $BTAttr{"Name"}) {
2814 return ();
2815 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002816 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002817 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002818 if(my $Size = getSize($TypeId)) {
2819 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2820 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002822 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2823 }
2824 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002825 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002828 else
2829 {
2830 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002831 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002832 $TypeAttr{"Name"} = $1."[]".$2;
2833 }
2834 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002835 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002837 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002838 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002839 if($BTAttr{"Header"}) {
2840 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002841 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002842 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002843 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2844 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002845 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002846 return ();
2847 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002848 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002849 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002850 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002851 if($TypeAttr{"Name"})
2852 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002853 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002854
2855 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2856 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002857 { # NOTE: register only one int: with built-in decl
2858 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2859 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2860 }
2861 }
2862 return %TypeAttr;
2863 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002864 else {
2865 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002867 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002868 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2869 {
2870 %TypeAttr = getTrivialTypeAttr($TypeId);
2871 if($TypeAttr{"Name"})
2872 {
2873 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2874 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2875 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2876 }
2877 return %TypeAttr;
2878 }
2879 else {
2880 return ();
2881 }
2882 }
2883 elsif($TypeAttr{"Type"} eq "SizeOf")
2884 {
2885 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2886 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2887 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2888 if($TypeAttr{"Name"})
2889 {
2890 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2891 return %TypeAttr;
2892 }
2893 else {
2894 return ();
2895 }
2896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002897 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002898 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002899 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2900 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002901 return ();
2902 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002903 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002904 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002905 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002906 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002907 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002908 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002909 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002911 }
2912 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002913 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002914 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002915 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002916 return ();
2917 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002918 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002919 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002920 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002921 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002922 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002923 }
2924 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002925 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002926 {
2927 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002928 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002929 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002930 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002931 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2932 }
2933 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002934 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002935 }
2936 }
2937 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002938 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002939 }
2940 if($TypeAttr{"Type"} eq "Typedef")
2941 {
2942 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002943
2944 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2945 return ();
2946 }
2947
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002948 if(isAnon($TypeAttr{"Name"}))
2949 { # anon typedef to anon type: ._N
2950 return ();
2951 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002952
2953 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2954 { # artificial typedef of "struct X" to "X"
2955 $TypeAttr{"Artificial"} = 1;
2956 }
2957
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002958 if(my $NS = getNameSpace($TypeDeclId))
2959 {
2960 my $TypeName = $TypeAttr{"Name"};
2961 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2962 { # "some_type" is the typedef to "struct some_type" in C++
2963 if($3) {
2964 $TypeAttr{"Name"} = $3."::".$TypeName;
2965 }
2966 }
2967 else
2968 {
2969 $TypeAttr{"NameSpace"} = $NS;
2970 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002971
2972 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2973 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2974 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 if($BTAttr{"NameSpace"}
2976 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002977 { # types like "std::fpos<__mbstate_t>" are
2978 # not covered by typedefs in the TU dump
2979 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002980 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2981 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002982 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002983 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002984 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002985 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002987 }
2988 }
2989 }
2990 }
2991 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002992 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002993 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002995 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2996 { # typedef int*const TYPEDEF; // first
2997 # int foo(TYPEDEF p); // const is optimized out
2998 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2999 if($BTAttr{"Name"}=~/</)
3000 {
3001 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3002 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003004 }
3005 }
3006 }
3007 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3008 }
3009 if(not $TypeAttr{"Size"})
3010 {
3011 if($TypeAttr{"Type"} eq "Pointer") {
3012 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3013 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003014 elsif($BTAttr{"Size"}) {
3015 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003016 }
3017 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003018 if(my $Algn = getAlgn($TypeId)) {
3019 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3020 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003021 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003022 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3023 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003024 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003025 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003026 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003027 { # typedef to "class Class"
3028 # should not be registered in TName_Tid
3029 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3030 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032 }
3033 return %TypeAttr;
3034 }
3035}
3036
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003037sub getTreeVec($)
3038{
3039 my %Vector = ();
3040 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3041 {
3042 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3043 { # string length is N-1 because of the null terminator
3044 $Vector{$1} = $2;
3045 }
3046 }
3047 return \%Vector;
3048}
3049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050sub get_TemplateParam($$)
3051{
3052 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003053 return () if(not $Type_Id);
3054 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3055 return () if(not $NodeType);
3056 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003057 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003058 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003059 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 my $Num = getNodeIntCst($Type_Id);
3061 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003062 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003063 }
3064 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003065 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003066 }
3067 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003068 elsif($NodeType eq "string_cst") {
3069 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003071 elsif($NodeType eq "tree_vec")
3072 {
3073 my $Vector = getTreeVec($Type_Id);
3074 my @Params = ();
3075 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3076 {
3077 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3078 push(@Params, $P2);
3079 }
3080 }
3081 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003082 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003083 elsif($NodeType eq "parm_decl")
3084 {
3085 (getNameByInfo($Type_Id));
3086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003087 else
3088 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003089 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003090 my $PName = $ParamAttr{"Name"};
3091 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003092 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003094 if($PName=~/\>/)
3095 {
3096 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 $PName = $Cover;
3098 }
3099 }
3100 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003101 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3103 # template<typename _Key, typename _Compare = std::less<_Key>
3104 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3105 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3106 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3107 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003108 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003109 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003110 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 }
3112}
3113
3114sub cover_stdcxx_typedef($)
3115{
3116 my $TypeName = $_[0];
3117 if(my @Covers = sort {length($a)<=>length($b)}
3118 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3119 { # take the shortest typedef
3120 # FIXME: there may be more than
3121 # one typedefs to the same type
3122 return $Covers[0];
3123 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003124 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003125 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3126 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3127 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003128 if(my $Cover = $Covers[0])
3129 {
3130 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3131 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003134 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003135}
3136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003137sub getNodeIntCst($)
3138{
3139 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003140 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003141 if($EnumMembName_Id{$Version}{$CstId}) {
3142 return $EnumMembName_Id{$Version}{$CstId};
3143 }
3144 elsif((my $Value = getTreeValue($CstId)) ne "")
3145 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003146 if($Value eq "0")
3147 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003148 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003149 return "false";
3150 }
3151 else {
3152 return "0";
3153 }
3154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003155 elsif($Value eq "1")
3156 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003157 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158 return "true";
3159 }
3160 else {
3161 return "1";
3162 }
3163 }
3164 else {
3165 return $Value;
3166 }
3167 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003168 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169}
3170
3171sub getNodeStrCst($)
3172{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003173 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3174 {
3175 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003176 {
3177 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3178 { # string length is N-1 because of the null terminator
3179 return substr($1, 0, $2-1);
3180 }
3181 else
3182 { # identifier_node
3183 return substr($1, 0, $2);
3184 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003186 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003187 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003188}
3189
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003190sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003191{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3194 if($Type eq "FieldPtr") {
3195 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3196 }
3197 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3198 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003199 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003200 if($Type eq "MethodPtr")
3201 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003202 if(my $Size = getSize($TypeId))
3203 {
3204 $Size/=$BYTE_SIZE;
3205 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003207 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003208 if(my $Algn = getAlgn($TypeId)) {
3209 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003211 # Return
3212 if($Type eq "FieldPtr")
3213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003214 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003215 if($ReturnAttr{"Name"}) {
3216 $MemPtrName .= $ReturnAttr{"Name"};
3217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003218 $TypeAttr{"Return"} = $PtrId;
3219 }
3220 else
3221 {
3222 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3223 {
3224 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003225 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3226 if(not $ReturnAttr{"Name"})
3227 { # templates
3228 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003229 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003230 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003231 $TypeAttr{"Return"} = $ReturnTypeId;
3232 }
3233 }
3234 # Class
3235 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3236 {
3237 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003238 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003239 if($Class{"Name"}) {
3240 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3241 }
3242 else {
3243 $MemPtrName .= " (*)";
3244 }
3245 }
3246 else {
3247 $MemPtrName .= " (*)";
3248 }
3249 # Parameters
3250 if($Type eq "FuncPtr"
3251 or $Type eq "MethodPtr")
3252 {
3253 my @ParamTypeName = ();
3254 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3255 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003256 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003257 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003258 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003260 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3261 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003263 my $PTypeId = $1;
3264 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 if(not $ParamAttr{"Name"})
3266 { # templates (template_type_parm), etc.
3267 return ();
3268 }
3269 if($ParamAttr{"Name"} eq "void") {
3270 last;
3271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003272 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003273 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003274 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003275 push(@ParamTypeName, $ParamAttr{"Name"});
3276 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003277 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3278 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003279 }
3280 else {
3281 last;
3282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003284 else {
3285 last;
3286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003287 }
3288 }
3289 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3290 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003291 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003292 return %TypeAttr;
3293}
3294
3295sub getTreeTypeName($)
3296{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003297 my $TypeId = $_[0];
3298 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003299 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003301 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302 if(my $Name = getNameByInfo($TypeId))
3303 { # bit_size_type
3304 return $Name;
3305 }
3306 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307 return "unsigned int";
3308 }
3309 else {
3310 return "int";
3311 }
3312 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003313 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003314 return getNameByInfo($1);
3315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003317 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318}
3319
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003321{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003322 my $Ptd = pointTo($_[0]);
3323 return 0 if(not $Ptd);
3324 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003325 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003326 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3327 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003328 }
3329 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003330 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3331 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003332 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003333 if($InfoT1 eq "pointer_type"
3334 and $InfoT2 eq "function_type") {
3335 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003336 }
3337 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003338 return 0;
3339}
3340
3341sub isMethodPtr($)
3342{
3343 my $Ptd = pointTo($_[0]);
3344 return 0 if(not $Ptd);
3345 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3346 {
3347 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3348 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3349 and $Info=~/ ptrmem /) {
3350 return 1;
3351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003352 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003353 return 0;
3354}
3355
3356sub isFieldPtr($)
3357{
3358 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3359 {
3360 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3361 and $Info=~/ ptrmem /) {
3362 return 1;
3363 }
3364 }
3365 return 0;
3366}
3367
3368sub pointTo($)
3369{
3370 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3371 {
3372 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3373 return $1;
3374 }
3375 }
3376 return "";
3377}
3378
3379sub getTypeTypeByTypeId($)
3380{
3381 my $TypeId = $_[0];
3382 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3383 {
3384 my $NType = $NodeType{$TType};
3385 if($NType eq "Intrinsic") {
3386 return $NType;
3387 }
3388 elsif(isFuncPtr($TypeId)) {
3389 return "FuncPtr";
3390 }
3391 elsif(isMethodPtr($TypeId)) {
3392 return "MethodPtr";
3393 }
3394 elsif(isFieldPtr($TypeId)) {
3395 return "FieldPtr";
3396 }
3397 elsif($NType ne "Other") {
3398 return $NType;
3399 }
3400 }
3401 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003402}
3403
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003404my %UnQual = (
3405 "r"=>"restrict",
3406 "v"=>"volatile",
3407 "c"=>"const",
3408 "cv"=>"const volatile"
3409);
3410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003411sub getQual($)
3412{
3413 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003414 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3415 {
3416 my ($Qual, $To) = ();
3417 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3418 $Qual = $UnQual{$1};
3419 }
3420 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3421 $To = $1;
3422 }
3423 if($Qual and $To) {
3424 return ($Qual, $To);
3425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003426 }
3427 return ();
3428}
3429
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003430sub getQualType($)
3431{
3432 if($_[0] eq "const volatile") {
3433 return "ConstVolatile";
3434 }
3435 return ucfirst($_[0]);
3436}
3437
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003438sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003440 my $TypeId = $_[0];
3441 my $TypeDeclId = getTypeDeclId($TypeId);
3442 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003443 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003444 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3445 return "Typedef";
3446 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003447 }
3448 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3449 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003450 if(($Qual or $To) and $TypeDeclId
3451 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003452 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003453 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003455 elsif(not $MissedBase_R{$Version}{$TypeId}
3456 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003457 return "Typedef";
3458 }
3459 elsif($Qual)
3460 { # qualified types
3461 return getQualType($Qual);
3462 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003463
3464 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3465 { # typedef struct { ... } name
3466 $TypeTypedef{$Version}{$TypeId} = $1;
3467 }
3468
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469 my $TypeType = getTypeTypeByTypeId($TypeId);
3470 if($TypeType eq "Struct")
3471 {
3472 if($TypeDeclId
3473 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3474 return "Template";
3475 }
3476 }
3477 return $TypeType;
3478}
3479
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003480sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003481{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003482 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003483 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003484 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3485 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3486 return 0;
3487 }
3488 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3489 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003490 if(my $TDid = getTypeDeclId($_[0]))
3491 {
3492 if(getTypeId($TDid) eq $_[0]
3493 and getNameByInfo($TDid))
3494 {
3495 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3496 return $1;
3497 }
3498 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003499 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003500 }
3501 }
3502 return 0;
3503}
3504
3505sub selectBaseType($)
3506{
3507 my $TypeId = $_[0];
3508 if(defined $MissedTypedef{$Version}{$TypeId})
3509 { # add missed typedefs
3510 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3511 return ($TypeId, "");
3512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003513 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003514 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3515 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003516
3517 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3518 my $MB = $MissedBase{$Version}{$TypeId};
3519
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003520 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003522 and (getTypeId($1) ne $TypeId)
3523 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003524 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003525 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003527 elsif($MB)
3528 { # add base
3529 return ($MB, "");
3530 }
3531 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003533 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003535 elsif($Qual or $To)
3536 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003537 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003538 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003539 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003540 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003541 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003542 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003544 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003545 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003546 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003547 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003550 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003551 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003552 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003553 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003554 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003556 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003557
3558 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003559}
3560
3561sub getSymbolInfo_All()
3562{
3563 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3564 { # reverse order
3565 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003566 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003567 }
3568 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003569
3570 if($ADD_TMPL_INSTANCES)
3571 {
3572 # templates
3573 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3574 {
3575 my %Map = ();
3576
3577 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3578 {
3579 if(defined $TemplateMap{$Version}{$ClassId})
3580 {
3581 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3582 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3583 }
3584 }
3585 }
3586
3587 if(defined $TemplateMap{$Version}{$Sid})
3588 {
3589 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3590 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3591 }
3592 }
3593
3594 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3595 {
3596 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3597 {
3598 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3599 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3600 }
3601 }
3602 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3603 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3604 }
3605 }
3606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003607}
3608
3609sub getVarInfo_All()
3610{
3611 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3612 { # reverse order
3613 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003614 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003615 }
3616 }
3617}
3618
3619sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003620 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003621}
3622
3623sub getVarInfo($)
3624{
3625 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003626 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003627 {
3628 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3629 if($NSInfoType and $NSInfoType eq "function_decl") {
3630 return;
3631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003632 }
3633 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3634 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3635 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3636 delete($SymbolInfo{$Version}{$InfoId});
3637 return;
3638 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003639 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003640 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003641 delete($SymbolInfo{$Version}{$InfoId});
3642 return;
3643 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003644 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3645 delete($SymbolInfo{$Version}{$InfoId});
3646 return;
3647 }
3648 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003649 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3650 {
3651 if($OSgroup eq "windows")
3652 { # cut the offset
3653 $MnglName=~s/\@\d+\Z//g;
3654 }
3655 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003658 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003659 { # validate mangled name
3660 delete($SymbolInfo{$Version}{$InfoId});
3661 return;
3662 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003663 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003664 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003665 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003666 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003667 }
3668 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3669 { # non-public global data
3670 delete($SymbolInfo{$Version}{$InfoId});
3671 return;
3672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003674 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003675 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003676 if(not defined $TypeInfo{$Version}{$Rid}
3677 or not $TypeInfo{$Version}{$Rid}{"Name"})
3678 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003679 delete($SymbolInfo{$Version}{$InfoId});
3680 return;
3681 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003682 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3683 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003684 if(defined $Val) {
3685 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003687 }
3688 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003689 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3690 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003691 if(not defined $TypeInfo{$Version}{$ClassId}
3692 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003694 delete($SymbolInfo{$Version}{$InfoId});
3695 return;
3696 }
3697 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003698 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3699 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003700 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003701 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003702 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003703 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003704 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003705 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003706 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003707 if(not $CheckHeadersOnly)
3708 {
3709 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3710 {
3711 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3712 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3713 {
3714 if(link_symbol($ShortName, $Version, "-Deps"))
3715 { # "const" global data is mangled as _ZL... in the TU dump
3716 # but not mangled when compiling a C shared library
3717 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3718 }
3719 }
3720 }
3721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003722 if($COMMON_LANGUAGE{$Version} eq "C++")
3723 {
3724 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3725 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003726 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003727 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3728 }
3729 }
3730 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3731 { # try to mangle symbol (link with libraries)
3732 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3733 }
3734 if($OStarget eq "windows")
3735 {
3736 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3737 { # link MS C++ symbols from library with GCC symbols from headers
3738 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3739 }
3740 }
3741 }
3742 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3743 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003745 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3746 {
3747 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3748 { # non-target symbols
3749 delete($SymbolInfo{$Version}{$InfoId});
3750 return;
3751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003752 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003753 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3754 {
3755 if(defined $MissedTypedef{$Version}{$Rid})
3756 {
3757 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3758 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3759 }
3760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003761 }
3762 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003763 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003764 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3765 }
3766 if($ShortName=~/\A(_Z|\?)/) {
3767 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3768 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003769
3770 if($ExtraDump) {
3771 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003773}
3774
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003775sub isConstType($$)
3776{
3777 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003778 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003779 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003780 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003781 }
3782 return ($Base{"Type"} eq "Const");
3783}
3784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003785sub getTrivialName($$)
3786{
3787 my ($TypeInfoId, $TypeId) = @_;
3788 my %TypeAttr = ();
3789 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3790 if(not $TypeAttr{"Name"}) {
3791 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3792 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003793 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003794 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003795 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003796 if(isAnon($TypeAttr{"Name"}))
3797 {
3798 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003799 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003800 { # searching for a first not anon scope
3801 if($NSId eq $NameSpaceId) {
3802 last;
3803 }
3804 else
3805 {
3806 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3807 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003808 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003809 last;
3810 }
3811 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003812 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003813 }
3814 }
3815 else
3816 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003817 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003818 {
3819 if($NameSpaceId ne $TypeId) {
3820 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003822 }
3823 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003824 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003825 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3826 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003827 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003829 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003830 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003832 if($TypeAttr{"NameSpace"}) {
3833 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003835 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003836 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3837 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003838 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003839 if(my @TParams = getTParams($TypeId, "Type")) {
3840 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3841 }
3842 else {
3843 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003845 }
3846 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3847}
3848
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003849sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003850{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003851 my $TypeId = $_[0];
3852 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003853
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003854 my %TypeAttr = ();
3855
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003856 if($TemplateDecl{$Version}{$TypeId})
3857 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003858 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003859 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003860
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 setTypeAccess($TypeId, \%TypeAttr);
3862 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3863 if(isBuiltIn($TypeAttr{"Header"}))
3864 {
3865 delete($TypeAttr{"Header"});
3866 delete($TypeAttr{"Line"});
3867 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003868
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003869 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003870 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3871 if(not $TypeAttr{"Name"}) {
3872 return ();
3873 }
3874 if(not $TypeAttr{"NameSpace"}) {
3875 delete($TypeAttr{"NameSpace"});
3876 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003877
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003878 if($TypeAttr{"Type"} eq "Intrinsic")
3879 {
3880 if(defined $TypeAttr{"Header"})
3881 {
3882 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3883 { # support for SUSE 11.2
3884 # integer_type has srcp dump{1-2}.i
3885 delete($TypeAttr{"Header"});
3886 }
3887 }
3888 }
3889
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003890 my $Tmpl = undef;
3891
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003892 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003893 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003894 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3895
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003896 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003897 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003898 foreach my $Pos (0 .. $#TParams)
3899 {
3900 my $Val = $TParams[$Pos];
3901 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3902
3903 if(not defined $TypeAttr{"Template"})
3904 {
3905 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3906
3907 if($Base{"Type"} eq "TemplateParam"
3908 or defined $Base{"Template"}) {
3909 $TypeAttr{"Template"} = 1;
3910 }
3911 }
3912
3913 if($Tmpl)
3914 {
3915 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3916 {
3917 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3918
3919 if($Val eq $Arg) {
3920 $TypeAttr{"Template"} = 1;
3921 }
3922 }
3923 }
3924 }
3925
3926 if($Tmpl)
3927 {
3928 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3929 {
3930 if($Pos>$#TParams)
3931 {
3932 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3933 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3934 }
3935 }
3936 }
3937 }
3938
3939 if($ADD_TMPL_INSTANCES)
3940 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003941 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003942 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003943 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003944 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003945 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003946 {
3947 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3948 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3949 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003950 }
3951 if(not getTreeAttr_Binf($TypeId))
3952 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003953 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3954 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3955 }
3956 }
3957 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003958 }
3959 }
3960 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003961
3962 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3963
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003964 if(my $Size = getSize($TypeId))
3965 {
3966 $Size = $Size/$BYTE_SIZE;
3967 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003969 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003970 {
3971 if($ExtraDump)
3972 {
3973 if(not defined $TypeAttr{"Memb"}
3974 and not $Tmpl)
3975 { # declaration only
3976 $TypeAttr{"Forward"} = 1;
3977 }
3978 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003979 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003981 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003982 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003983 {
3984 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003985 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003986 }
3987 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003988 or $TypeAttr{"Type"} eq "Class")
3989 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003990 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003991 if($Skip) {
3992 return ();
3993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003994 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003995 if(my $Algn = getAlgn($TypeId)) {
3996 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003998 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003999
4000 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4001 {
4002 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004003 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004004 {
4005 if(not isAnon($TypeAttr{"Name"})) {
4006 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4007 }
4008 }
4009 }
4010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004011 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004012 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4013 {
4014 my @Entries = split(/\n/, $VTable);
4015 foreach (1 .. $#Entries)
4016 {
4017 my $Entry = $Entries[$_];
4018 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004019 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004020 }
4021 }
4022 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004023
4024 if($TypeAttr{"Type"} eq "Enum")
4025 {
4026 if(not $TypeAttr{"NameSpace"})
4027 {
4028 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4029 {
4030 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004031 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004032 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004033 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004034 "Header"=>$TypeAttr{"Header"}
4035 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004036 if(isAnon($TypeAttr{"Name"}))
4037 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004038 if($ExtraDump
4039 or is_target_header($TypeAttr{"Header"}, $Version))
4040 {
4041 %{$Constants{$Version}{$MName}} = (
4042 "Value" => $MVal,
4043 "Header" => $TypeAttr{"Header"}
4044 );
4045 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004046 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004047 }
4048 }
4049 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004050 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004051 {
4052 if(defined $TypedefToAnon{$TypeId}) {
4053 $TypeAttr{"AnonTypedef"} = 1;
4054 }
4055 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004057 return %TypeAttr;
4058}
4059
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004060sub simplifyVTable($)
4061{
4062 my $Content = $_[0];
4063 if($Content=~s/ \[with (.+)]//)
4064 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4065 if(my @Elems = separate_Params($1, 0, 0))
4066 {
4067 foreach my $Elem (@Elems)
4068 {
4069 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4070 {
4071 my ($Arg, $Val) = ($1, $2);
4072
4073 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4074 $Content=~s/,\s*$Arg\b//g;
4075 }
4076 else {
4077 $Content=~s/\b$Arg\b/$Val/g;
4078 }
4079 }
4080 }
4081 }
4082 }
4083
4084 return $Content;
4085}
4086
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004087sub detect_lang($)
4088{
4089 my $TypeId = $_[0];
4090 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004091 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004092 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4094 }
4095 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004096 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004097 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004098 while($Fncs)
4099 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004100 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101 return 1;
4102 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004103 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004104 }
4105 }
4106 return 0;
4107}
4108
4109sub setSpec($$)
4110{
4111 my ($TypeId, $TypeAttr) = @_;
4112 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4113 if($Info=~/\s+spec\s+/) {
4114 $TypeAttr->{"Spec"} = 1;
4115 }
4116}
4117
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004118sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004120 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004121 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004122 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004124 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 my $Pos = 0;
4126 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4127 {
4128 my ($Access, $BInfoId) = ($1, $2);
4129 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004130
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004131 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004132 { # class A<N>:public A<N-1>
4133 next;
4134 }
4135
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004136 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4137 if(not $CType or $CType eq "template_type_parm"
4138 or $CType eq "typename_type")
4139 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004140 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004142 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004143 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004144 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4145 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004146 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004147 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4148 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004149 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004150 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004151 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004152 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4153 }
4154 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004155 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004156 }
4157 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004158 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159}
4160
4161sub getBinfClassId($)
4162{
4163 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004164 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4165 return $1;
4166 }
4167
4168 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004169}
4170
4171sub unmangledFormat($$)
4172{
4173 my ($Name, $LibVersion) = @_;
4174 $Name = uncover_typedefs($Name, $LibVersion);
4175 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4176 $Name=~s/\(\w+\)(\d)/$1/;
4177 return $Name;
4178}
4179
4180sub modelUnmangled($$)
4181{
4182 my ($InfoId, $Compiler) = @_;
4183 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4184 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4185 }
4186 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4187 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4188 $PureSignature = "~".$PureSignature;
4189 }
4190 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4191 {
4192 my (@Params, @ParamTypes) = ();
4193 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4194 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4195 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4196 }
4197 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4198 { # checking parameters
4199 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004200 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004201 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004202 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004203
4204 if($PName eq "this"
4205 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4206 {
4207 next;
4208 }
4209
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004210 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004211 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004212 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004213 }
4214 @ParamTypes = (@ParamTypes, $PTName);
4215 }
4216 if(@ParamTypes) {
4217 $PureSignature .= "(".join(", ", @ParamTypes).")";
4218 }
4219 else
4220 {
4221 if($Compiler eq "MSVC")
4222 {
4223 $PureSignature .= "(void)";
4224 }
4225 else
4226 { # GCC
4227 $PureSignature .= "()";
4228 }
4229 }
4230 $PureSignature = delete_keywords($PureSignature);
4231 }
4232 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4233 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004234 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004235 $PureSignature = $ClassName."::".$PureSignature;
4236 }
4237 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4238 $PureSignature = $NS."::".$PureSignature;
4239 }
4240 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4241 $PureSignature .= " const";
4242 }
4243 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4244 $PureSignature .= " volatile";
4245 }
4246 my $ShowReturn = 0;
4247 if($Compiler eq "MSVC"
4248 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4249 {
4250 $ShowReturn=1;
4251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004252 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4253 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004254 {
4255 $ShowReturn=1;
4256 }
4257 if($ShowReturn)
4258 { # mangled names for template function specializations include return value
4259 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4260 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004261 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004262 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4263 $PureSignature = $ReturnName." ".$PureSignature;
4264 }
4265 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004266 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004267}
4268
4269sub mangle_symbol($$$)
4270{ # mangling for simple methods
4271 # see gcc-4.6.0/gcc/cp/mangle.c
4272 my ($InfoId, $LibVersion, $Compiler) = @_;
4273 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4274 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4275 }
4276 my $Mangled = "";
4277 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004278 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004279 }
4280 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004281 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004282 }
4283 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4284}
4285
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004286sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004287{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004288 my ($InfoId, $LibVersion) = @_;
4289 return "";
4290}
4291
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004292sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004293{ # see gcc-4.6.0/gcc/cp/mangle.c
4294 my ($InfoId, $LibVersion) = @_;
4295 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004296 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004297 my %Repl = ();# SN_ replacements
4298 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4299 {
4300 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4301 if($MangledClass!~/\AN/) {
4302 $MangledClass = "N".$MangledClass;
4303 }
4304 else {
4305 $MangledClass=~s/E\Z//;
4306 }
4307 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4308 $MangledClass=~s/\AN/NV/;
4309 }
4310 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4311 $MangledClass=~s/\AN/NK/;
4312 }
4313 $Mangled .= $MangledClass;
4314 }
4315 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4316 { # mangled by name due to the absence of structured info
4317 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4318 if($MangledNS!~/\AN/) {
4319 $MangledNS = "N".$MangledNS;
4320 }
4321 else {
4322 $MangledNS=~s/E\Z//;
4323 }
4324 $Mangled .= $MangledNS;
4325 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004326 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004327 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004328 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004329 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004330 foreach (@TPos) {
4331 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4332 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004333 }
4334 elsif($TmplParams)
4335 { # remangling mode
4336 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004337 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004338 }
4339 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4340 $Mangled .= "C1";
4341 }
4342 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4343 $Mangled .= "D0";
4344 }
4345 elsif($ShortName)
4346 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004347 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4348 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004349 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004350 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004351 { # "const" global data is mangled as _ZL...
4352 $Mangled .= "L";
4353 }
4354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004355 if($ShortName=~/\Aoperator(\W.*)\Z/)
4356 {
4357 my $Op = $1;
4358 $Op=~s/\A[ ]+//g;
4359 if(my $OpMngl = $OperatorMangling{$Op}) {
4360 $Mangled .= $OpMngl;
4361 }
4362 else { # conversion operator
4363 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4364 }
4365 }
4366 else {
4367 $Mangled .= length($ShortName).$ShortName;
4368 }
4369 if(@TParams)
4370 { # templates
4371 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004372 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004373 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4374 }
4375 $Mangled .= "E";
4376 }
4377 if(not $ClassId and @TParams) {
4378 add_substitution($ShortName, \%Repl, 0);
4379 }
4380 }
4381 if($ClassId or $NameSpace) {
4382 $Mangled .= "E";
4383 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004384 if(@TParams)
4385 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004386 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004387 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4388 }
4389 }
4390 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4391 {
4392 my @Params = ();
4393 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4394 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4395 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4396 }
4397 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4398 { # checking parameters
4399 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4400 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4401 }
4402 if(not @Params) {
4403 $Mangled .= "v";
4404 }
4405 }
4406 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4407 $Mangled = write_stdcxx_substitution($Mangled);
4408 if($Mangled eq "_Z") {
4409 return "";
4410 }
4411 return $Mangled;
4412}
4413
4414sub correct_incharge($$$)
4415{
4416 my ($InfoId, $LibVersion, $Mangled) = @_;
4417 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4418 {
4419 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004420 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004421 }
4422 }
4423 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4424 {
4425 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004426 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004427 }
4428 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004429 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004430 }
4431 }
4432 return $Mangled;
4433}
4434
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004435sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004436{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004437 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004438 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004439 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004440 return $Name;
4441 }
4442 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004443 while(my $CPos = find_center($TParams, "<"))
4444 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004445 $TParams = substr($TParams, $CPos);
4446 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004447 if($TParams=~s/\A<(.+)>\Z/$1/) {
4448 $Name=~s/<\Q$TParams\E>\Z//;
4449 }
4450 else
4451 { # error
4452 $TParams = "";
4453 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004454 return ($Name, $TParams);
4455}
4456
4457sub get_sub_ns($)
4458{
4459 my $Name = $_[0];
4460 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004461 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004462 {
4463 push(@NS, substr($Name, 0, $CPos));
4464 $Name = substr($Name, $CPos);
4465 $Name=~s/\A:://;
4466 }
4467 return (join("::", @NS), $Name);
4468}
4469
4470sub mangle_ns($$$)
4471{
4472 my ($Name, $LibVersion, $Repl) = @_;
4473 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4474 {
4475 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4476 $Mangled=~s/\AN(.+)E\Z/$1/;
4477 return $Mangled;
4478
4479 }
4480 else
4481 {
4482 my ($MangledNS, $SubNS) = ("", "");
4483 ($SubNS, $Name) = get_sub_ns($Name);
4484 if($SubNS) {
4485 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4486 }
4487 $MangledNS .= length($Name).$Name;
4488 add_substitution($MangledNS, $Repl, 0);
4489 return $MangledNS;
4490 }
4491}
4492
4493sub mangle_param($$$)
4494{
4495 my ($PTid, $LibVersion, $Repl) = @_;
4496 my ($MPrefix, $Mangled) = ("", "");
4497 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004498 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004499 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004500 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004501 if(not $BaseType_Name) {
4502 return "";
4503 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004504 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004505 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004506 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4507 while($Suffix=~/(&|\*|const)\Z/)
4508 {
4509 if($Suffix=~s/[ ]*&\Z//) {
4510 $MPrefix .= "R";
4511 }
4512 if($Suffix=~s/[ ]*\*\Z//) {
4513 $MPrefix .= "P";
4514 }
4515 if($Suffix=~s/[ ]*const\Z//)
4516 {
4517 if($MPrefix=~/R|P/
4518 or $Suffix=~/&|\*/) {
4519 $MPrefix .= "K";
4520 }
4521 }
4522 if($Suffix=~s/[ ]*volatile\Z//) {
4523 $MPrefix .= "V";
4524 }
4525 #if($Suffix=~s/[ ]*restrict\Z//) {
4526 #$MPrefix .= "r";
4527 #}
4528 }
4529 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4530 $Mangled .= $Token;
4531 }
4532 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4533 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004534 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004535 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004536 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004537 foreach (@TPos) {
4538 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4539 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004540 }
4541 elsif($TmplParams)
4542 { # remangling mode
4543 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004544 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004545 }
4546 my $MangledNS = "";
4547 my ($SubNS, $SName) = get_sub_ns($ShortName);
4548 if($SubNS) {
4549 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4550 }
4551 $MangledNS .= length($SName).$SName;
4552 if(@TParams) {
4553 add_substitution($MangledNS, $Repl, 0);
4554 }
4555 $Mangled .= "N".$MangledNS;
4556 if(@TParams)
4557 { # templates
4558 $Mangled .= "I";
4559 foreach my $TParam (@TParams) {
4560 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4561 }
4562 $Mangled .= "E";
4563 }
4564 $Mangled .= "E";
4565 }
4566 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4567 {
4568 if($BaseType{"Type"} eq "MethodPtr") {
4569 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4570 }
4571 else {
4572 $Mangled .= "PF";
4573 }
4574 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4575 my @Params = keys(%{$BaseType{"Param"}});
4576 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4577 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4578 }
4579 if(not @Params) {
4580 $Mangled .= "v";
4581 }
4582 $Mangled .= "E";
4583 }
4584 elsif($BaseType{"Type"} eq "FieldPtr")
4585 {
4586 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4587 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4588 }
4589 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4590 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4591 {
4592 if($Mangled eq $Optimized)
4593 {
4594 if($ShortName!~/::/)
4595 { # remove "N ... E"
4596 if($MPrefix) {
4597 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4598 }
4599 else {
4600 $Mangled=~s/\AN(.+)E\Z/$1/g;
4601 }
4602 }
4603 }
4604 else {
4605 $Mangled = $Optimized;
4606 }
4607 }
4608 add_substitution($Mangled, $Repl, 1);
4609 return $Mangled;
4610}
4611
4612sub mangle_template_param($$$)
4613{ # types + literals
4614 my ($TParam, $LibVersion, $Repl) = @_;
4615 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4616 return mangle_param($TPTid, $LibVersion, $Repl);
4617 }
4618 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4619 { # class_name<1u>::method(...)
4620 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4621 }
4622 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4623 { # class_name<(signed char)1>::method(...)
4624 return "L".$IntrinsicMangling{$1}.$2."E";
4625 }
4626 elsif($TParam eq "true")
4627 { # class_name<true>::method(...)
4628 return "Lb1E";
4629 }
4630 elsif($TParam eq "false")
4631 { # class_name<true>::method(...)
4632 return "Lb0E";
4633 }
4634 else { # internal error
4635 return length($TParam).$TParam;
4636 }
4637}
4638
4639sub add_substitution($$$)
4640{
4641 my ($Value, $Repl, $Rec) = @_;
4642 if($Rec)
4643 { # subtypes
4644 my @Subs = ($Value);
4645 while($Value=~s/\A(R|P|K)//) {
4646 push(@Subs, $Value);
4647 }
4648 foreach (reverse(@Subs)) {
4649 add_substitution($_, $Repl, 0);
4650 }
4651 return;
4652 }
4653 return if($Value=~/\AS(\d*)_\Z/);
4654 $Value=~s/\AN(.+)E\Z/$1/g;
4655 return if(defined $Repl->{$Value});
4656 return if(length($Value)<=1);
4657 return if($StdcxxMangling{$Value});
4658 # check for duplicates
4659 my $Base = $Value;
4660 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4661 {
4662 my $Num = $Repl->{$Type};
4663 my $Replace = macro_mangle($Num);
4664 $Base=~s/\Q$Replace\E/$Type/;
4665 }
4666 if(my $OldNum = $Repl->{$Base})
4667 {
4668 $Repl->{$Value} = $OldNum;
4669 return;
4670 }
4671 my @Repls = sort {$b<=>$a} values(%{$Repl});
4672 if(@Repls) {
4673 $Repl->{$Value} = $Repls[0]+1;
4674 }
4675 else {
4676 $Repl->{$Value} = -1;
4677 }
4678 # register duplicates
4679 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004680 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004681 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4682 {
4683 next if($Base eq $Type);
4684 my $Num = $Repl->{$Type};
4685 my $Replace = macro_mangle($Num);
4686 $Base=~s/\Q$Type\E/$Replace/;
4687 $Repl->{$Base} = $Repl->{$Value};
4688 }
4689}
4690
4691sub macro_mangle($)
4692{
4693 my $Num = $_[0];
4694 if($Num==-1) {
4695 return "S_";
4696 }
4697 else
4698 {
4699 my $Code = "";
4700 if($Num<10)
4701 { # S0_, S1_, S2_, ...
4702 $Code = $Num;
4703 }
4704 elsif($Num>=10 and $Num<=35)
4705 { # SA_, SB_, SC_, ...
4706 $Code = chr(55+$Num);
4707 }
4708 else
4709 { # S10_, S11_, S12_
4710 $Code = $Num-26; # 26 is length of english alphabet
4711 }
4712 return "S".$Code."_";
4713 }
4714}
4715
4716sub write_stdcxx_substitution($)
4717{
4718 my $Mangled = $_[0];
4719 if($StdcxxMangling{$Mangled}) {
4720 return $StdcxxMangling{$Mangled};
4721 }
4722 else
4723 {
4724 my @Repls = keys(%StdcxxMangling);
4725 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4726 foreach my $MangledType (@Repls)
4727 {
4728 my $Replace = $StdcxxMangling{$MangledType};
4729 #if($Mangled!~/$Replace/) {
4730 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4731 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4732 #}
4733 }
4734 }
4735 return $Mangled;
4736}
4737
4738sub write_substitution($$)
4739{
4740 my ($Mangled, $Repl) = @_;
4741 if(defined $Repl->{$Mangled}
4742 and my $MnglNum = $Repl->{$Mangled}) {
4743 $Mangled = macro_mangle($MnglNum);
4744 }
4745 else
4746 {
4747 my @Repls = keys(%{$Repl});
4748 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4749 # FIXME: how to apply replacements? by num or by pos
4750 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4751 foreach my $MangledType (@Repls)
4752 {
4753 my $Replace = macro_mangle($Repl->{$MangledType});
4754 if($Mangled!~/$Replace/) {
4755 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4756 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4757 }
4758 }
4759 }
4760 return $Mangled;
4761}
4762
4763sub delete_keywords($)
4764{
4765 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004766 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004767 return $TypeName;
4768}
4769
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004770sub uncover_typedefs($$)
4771{
4772 my ($TypeName, $LibVersion) = @_;
4773 return "" if(not $TypeName);
4774 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4775 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4776 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004777 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004778 while($TypeName_New ne $TypeName_Pre)
4779 {
4780 $TypeName_Pre = $TypeName_New;
4781 my $TypeName_Copy = $TypeName_New;
4782 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004783 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004785 if(not $Intrinsic_Keywords{$1}) {
4786 $Words{$1} = 1;
4787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004788 }
4789 foreach my $Word (keys(%Words))
4790 {
4791 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4792 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004793 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004794 if($BaseType_Name=~/\([\*]+\)/)
4795 { # FuncPtr
4796 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4797 {
4798 my $Type_Suffix = $1;
4799 $TypeName_New = $BaseType_Name;
4800 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004801 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004802 }
4803 }
4804 }
4805 else
4806 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004807 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004808 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004809 }
4810 }
4811 }
4812 }
4813 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4814}
4815
4816sub isInternal($)
4817{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004818 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4819 {
4820 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4821 {
4822 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4823 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4824 return 1;
4825 }
4826 }
4827 }
4828 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004829}
4830
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004831sub getDataVal($$)
4832{
4833 my ($InfoId, $TypeId) = @_;
4834 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4835 {
4836 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4837 {
4838 if(defined $LibInfo{$Version}{"info_type"}{$1}
4839 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004840 {
4841 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004842 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004843 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4844 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004845 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004846 if(my $Addr = getTreeAttr_Op($1)) {
4847 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004848 }
4849 }
4850 }
4851 }
4852 else {
4853 return getInitVal($1, $TypeId);
4854 }
4855 }
4856 }
4857 return undef;
4858}
4859
4860sub getInitVal($$)
4861{
4862 my ($InfoId, $TypeId) = @_;
4863 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4864 {
4865 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4866 {
4867 if($InfoType eq "integer_cst")
4868 {
4869 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004870 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004871 { # characters
4872 $Val = chr($Val);
4873 }
4874 return $Val;
4875 }
4876 elsif($InfoType eq "string_cst") {
4877 return getNodeStrCst($InfoId);
4878 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004879 elsif($InfoType eq "var_decl")
4880 {
4881 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4882 return $Name;
4883 }
4884 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004885 }
4886 }
4887 return undef;
4888}
4889
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004890sub set_Class_And_Namespace($)
4891{
4892 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004893 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004894 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004895 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004896 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004897 my $NSInfoId = $1;
4898 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4899 {
4900 if($InfoType eq "namespace_decl") {
4901 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4902 }
4903 elsif($InfoType eq "record_type") {
4904 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4905 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004907 }
4908 }
4909 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4910 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004911 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004912 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004913 { # skip
4914 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004917
4918 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004919}
4920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004921sub debugMangling($)
4922{
4923 my $LibVersion = $_[0];
4924 my %Mangled = ();
4925 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4926 {
4927 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4928 {
4929 if($Mngl=~/\A(_Z|\?)/) {
4930 $Mangled{$Mngl}=$InfoId;
4931 }
4932 }
4933 }
4934 translateSymbols(keys(%Mangled), $LibVersion);
4935 foreach my $Mngl (keys(%Mangled))
4936 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004937 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4938 my $U2 = $tr_name{$Mngl};
4939 if($U1 ne $U2) {
4940 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004941 }
4942 }
4943}
4944
4945sub linkSymbol($)
4946{ # link symbols from shared libraries
4947 # with the symbols from header files
4948 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004949 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004950 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004951 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4952 or $EMERGENCY_MODE_48)
4953 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4954 # 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 +03004955 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004956 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004957 {
4958 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4959 return correct_incharge($InfoId, $Version, $Mangled);
4960 }
4961 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004962 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004963 or not $BinaryOnly
4964 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004965 { # 1. --headers-only mode
4966 # 2. not mangled src-only symbols
4967 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4968 return $Mangled;
4969 }
4970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004971 }
4972 return "";
4973}
4974
4975sub setLanguage($$)
4976{
4977 my ($LibVersion, $Lang) = @_;
4978 if(not $UserLang) {
4979 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4980 }
4981}
4982
4983sub getSymbolInfo($)
4984{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004985 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004986 if(isInternal($InfoId)) {
4987 return;
4988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004989 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4990 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004991 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004993 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004994 return;
4995 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004996 setFuncAccess($InfoId);
4997 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004998 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4999 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005000 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005001 return;
5002 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005003
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005004 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005005 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005006 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005007 if(not defined $TypeInfo{$Version}{$Return}
5008 or not $TypeInfo{$Version}{$Return}{"Name"})
5009 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005010 delete($SymbolInfo{$Version}{$InfoId});
5011 return;
5012 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005013 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005014 }
5015 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5016 {
5017 if(defined $MissedTypedef{$Version}{$Rid})
5018 {
5019 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5020 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5021 }
5022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005023 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005024 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5025 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005026 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005027 my $Orig = getFuncOrig($InfoId);
5028 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005029 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5030 {
5031 delete($SymbolInfo{$Version}{$InfoId});
5032 return;
5033 }
5034
5035 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005036 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005037 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005038 return;
5039 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005040
5041 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005042 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005043 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5044
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005045 my @TParams = getTParams($Orig, "Func");
5046 if(not @TParams)
5047 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005048 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005049 return;
5050 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005051 foreach my $Pos (0 .. $#TParams)
5052 {
5053 my $Val = $TParams[$Pos];
5054 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5055
5056 if($Tmpl)
5057 {
5058 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5059 {
5060 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5061 }
5062 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005063 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005064
5065 if($Tmpl)
5066 {
5067 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5068 {
5069 if($Pos>$#TParams)
5070 {
5071 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5072 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5073 }
5074 }
5075 }
5076
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005077 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5078 { # operator<< <T>, operator>> <T>
5079 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5080 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005081 if(@TParams) {
5082 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5083 }
5084 else {
5085 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5086 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005087 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005088 }
5089 else
5090 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005091 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005092 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005093 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5094 {
5095 if($OSgroup eq "windows")
5096 { # cut the offset
5097 $MnglName=~s/\@\d+\Z//g;
5098 }
5099 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5100
5101 # NOTE: mangling of some symbols may change depending on GCC version
5102 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5103 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5104 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005105
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005106 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005107 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005108 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005109 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005110 return;
5111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005112 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005113 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005114 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005115 if($Skip)
5116 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005117 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005118 return;
5119 }
5120 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005121 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5122 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5123 }
5124
5125 if(set_Class_And_Namespace($InfoId))
5126 {
5127 delete($SymbolInfo{$Version}{$InfoId});
5128 return;
5129 }
5130
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005131 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5132 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005133 if(not defined $TypeInfo{$Version}{$ClassId}
5134 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005136 delete($SymbolInfo{$Version}{$InfoId});
5137 return;
5138 }
5139 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005140 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5141 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005142 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005143 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005144 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005145 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005147 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005148 }
5149 if($COMMON_LANGUAGE{$Version} eq "C++")
5150 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005151 # C++ or --headers-only mode
5152 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005153 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005154 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5155 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005156 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005157 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005158 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005159 if(my $Mangled = linkSymbol($InfoId)) {
5160 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005161 }
5162 }
5163 if($OStarget eq "windows")
5164 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005165 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005166 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005167 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005169 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005170 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005171 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005172 }
5173 }
5174 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005175 else
5176 { # not mangled in C
5177 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5178 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005179 if(not $CheckHeadersOnly
5180 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5181 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5182 {
5183 my $Incorrect = 0;
5184
5185 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5186 {
5187 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5188 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5189 { # mangled in the TU dump, but not mangled in the library
5190 $Incorrect = 1;
5191 }
5192 }
5193 else
5194 {
5195 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5196 { # all C++ functions are not mangled in the TU dump
5197 $Incorrect = 1;
5198 }
5199 }
5200 if($Incorrect)
5201 {
5202 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5203 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5204 }
5205 }
5206 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005207 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005208 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005209 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005210 return;
5211 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005212 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005213 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005214 { # identify virtual and pure virtual functions
5215 # NOTE: constructors cannot be virtual
5216 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5217 # in the TU dump, so taking it from the original symbol
5218 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5219 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5220 { # NOTE: D2 destructors are not present in a v-table
5221 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005223 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005224 if(isInline($InfoId)) {
5225 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005226 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005227 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005228 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005230 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5231 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005232 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005233 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005234 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005235 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005236 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 }
5238 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005239 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5240 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005241 if(not $ExtraDump)
5242 {
5243 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5244 { # non-target symbols
5245 delete($SymbolInfo{$Version}{$InfoId});
5246 return;
5247 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5251 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5252 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5253 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005255 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5256 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005257 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005258 return;
5259 }
5260 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005261 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005265 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 return;
5267 }
5268 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005270 }
5271 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005272 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5273 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5274 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005275 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005276 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5277 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005278 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005279 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005281 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005282 }
5283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005284 if(getFuncLink($InfoId) eq "Static") {
5285 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005286 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005287 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5288 {
5289 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5290 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005291 if($Unmangled=~/\.\_\d/)
5292 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005293 delete($SymbolInfo{$Version}{$InfoId});
5294 return;
5295 }
5296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005297 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005298
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5300 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005302 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5303 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005305
5306 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5307 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5308 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005309
5310 if($ExtraDump) {
5311 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5312 }
5313}
5314
5315sub guessHeader($)
5316{
5317 my $InfoId = $_[0];
5318 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5319 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5320 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5321 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5322 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5323 {
5324 if(get_filename($HPath) eq $Header)
5325 {
5326 my $HDir = get_filename(get_dirname($HPath));
5327 if($HDir ne "include"
5328 and $HDir=~/\A[a-z]+\Z/i) {
5329 return join_P($HDir, $Header);
5330 }
5331 }
5332 }
5333 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005334}
5335
5336sub isInline($)
5337{ # "body: undefined" in the tree
5338 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005339 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5340 {
5341 if($Info=~/ undefined /i) {
5342 return 0;
5343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005344 }
5345 return 1;
5346}
5347
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005348sub hasThrow($)
5349{
5350 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5351 {
5352 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5353 return getTreeAttr_Unql($1, "unql");
5354 }
5355 }
5356 return 1;
5357}
5358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359sub getTypeId($)
5360{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005361 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5362 {
5363 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5364 return $1;
5365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005367 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005368}
5369
5370sub setTypeMemb($$)
5371{
5372 my ($TypeId, $TypeAttr) = @_;
5373 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005374 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005375 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005376 if($TypeType eq "Enum")
5377 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005378 my $MInfoId = getTreeAttr_Csts($TypeId);
5379 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005381 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5382 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005383 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005384 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5385 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005386 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005387 }
5388 }
5389 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5390 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005391 my $MInfoId = getTreeAttr_Flds($TypeId);
5392 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005393 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005394 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5395 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005396 if(not $IType or $IType ne "field_decl")
5397 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005398
5399 if($IType eq "var_decl")
5400 { # static field
5401 $StaticFields = 1;
5402 }
5403
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005404 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005405 next;
5406 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005407 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005408 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005409 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005410 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005411 }
5412 if(not $StructMembName)
5413 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005414 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005415 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005416 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005417 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5418 if(isAnon($UnnamedTName))
5419 { # rename unnamed fields to unnamed0, unnamed1, ...
5420 $StructMembName = "unnamed".($UnnamedPos++);
5421 }
5422 }
5423 }
5424 if(not $StructMembName)
5425 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005426 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005427 next;
5428 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005429 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005430 if(defined $MissedTypedef{$Version}{$MembTypeId})
5431 {
5432 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5433 $MembTypeId = $AddedTid;
5434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005435 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005436
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005437 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5438 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005439 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005440 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005441 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5442 }
5443 if($MInfo=~/spec:\s*mutable /)
5444 { # mutable fields
5445 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005446 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005447 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005448 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5449 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005450 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005451 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005452 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 }
5454 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005455 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005456 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5457 { # template
5458 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5459 }
5460 else {
5461 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005463 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005464
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005466 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467 }
5468 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005469
5470 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471}
5472
5473sub setFuncParams($)
5474{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005475 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005476 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005477
5478 my $FType = getFuncType($InfoId);
5479
5480 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005481 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005482 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5483 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005484 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005485 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005486 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005488 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005489 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005491 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005492 else
5493 { # skip
5494 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005496 # skip "this"-parameter
5497 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005498 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005499 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005500 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005501 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005502 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5503 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5504 if(not $ParamName)
5505 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005506 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005508 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5509 {
5510 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5511 $ParamTypeId = $AddedTid;
5512 }
5513 }
5514 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005515 if(not $PType or $PType eq "Unknown") {
5516 return 1;
5517 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005518 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005519 if(not $PTName) {
5520 return 1;
5521 }
5522 if($PTName eq "void") {
5523 last;
5524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005526 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005528 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529 $ParamInfoId = getNextElem($ParamInfoId);
5530 next;
5531 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005532 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005533
5534 if(my %Base = get_BaseType($ParamTypeId, $Version))
5535 {
5536 if(defined $Base{"Template"}) {
5537 return 1;
5538 }
5539 }
5540
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005541 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005542 if(my $Algn = getAlgn($ParamInfoId)) {
5543 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5544 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005545 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5546 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005547 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005548 }
5549 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005550 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005551 if($ParamName ne "this" or $FType ne "Method") {
5552 $PPos += 1;
5553 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005554 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005555 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005556 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557 }
5558 return 0;
5559}
5560
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005561sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005562{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005563 my ($InfoId, $Vtt_Pos) = @_;
5564 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005565 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005566 my $FType = getFuncType($InfoId);
5567
5568 if($FType eq "Method")
5569 {
5570 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005571 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 if(not $ParamListElemId)
5574 { # foo(...)
5575 return 1;
5576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005577 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005578 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005579 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005580 { # actual params: may differ from formal args
5581 # formal int*const
5582 # actual: int*
5583 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005584 {
5585 $Vtt_Pos=-1;
5586 $ParamListElemId = getNextElem($ParamListElemId);
5587 next;
5588 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005589 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5590 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005591 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005592 $HaveVoid = 1;
5593 last;
5594 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005595 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005596 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005597 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5598 {
5599 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5600 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5601 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005602 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005603 }
5604 }
5605 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5606 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005607 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005608 { # params
5609 if($OldId ne $ParamTypeId)
5610 {
5611 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5612 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5613
5614 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5615 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5616 }
5617 }
5618 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005619 }
5620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005621 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005622 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005623 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5624 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005625 if($PurpType eq "nop_expr")
5626 { # func ( const char* arg = (const char*)(void*)0 )
5627 $PurpId = getTreeAttr_Op($PurpId);
5628 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005629 my $Val = getInitVal($PurpId, $ParamTypeId);
5630 if(defined $Val) {
5631 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005633 }
5634 }
5635 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005636 if($Pos!=0 or $FType ne "Method") {
5637 $PPos += 1;
5638 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005639 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005640 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005641 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005642}
5643
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005644sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005645{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005646 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5647 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005648 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5649 return $1;
5650 }
5651 }
5652 return "";
5653}
5654
5655sub getTreeAttr_Chain($)
5656{
5657 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5658 {
5659 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5660 return $1;
5661 }
5662 }
5663 return "";
5664}
5665
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005666sub getTreeAttr_Unql($)
5667{
5668 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5669 {
5670 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5671 return $1;
5672 }
5673 }
5674 return "";
5675}
5676
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005677sub getTreeAttr_Scpe($)
5678{
5679 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5680 {
5681 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5682 return $1;
5683 }
5684 }
5685 return "";
5686}
5687
5688sub getTreeAttr_Type($)
5689{
5690 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5691 {
5692 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5693 return $1;
5694 }
5695 }
5696 return "";
5697}
5698
5699sub getTreeAttr_Name($)
5700{
5701 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5702 {
5703 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5704 return $1;
5705 }
5706 }
5707 return "";
5708}
5709
5710sub getTreeAttr_Mngl($)
5711{
5712 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5713 {
5714 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5715 return $1;
5716 }
5717 }
5718 return "";
5719}
5720
5721sub getTreeAttr_Prms($)
5722{
5723 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5724 {
5725 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5726 return $1;
5727 }
5728 }
5729 return "";
5730}
5731
5732sub getTreeAttr_Fncs($)
5733{
5734 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5735 {
5736 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5737 return $1;
5738 }
5739 }
5740 return "";
5741}
5742
5743sub getTreeAttr_Csts($)
5744{
5745 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5746 {
5747 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5748 return $1;
5749 }
5750 }
5751 return "";
5752}
5753
5754sub getTreeAttr_Purp($)
5755{
5756 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5757 {
5758 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5759 return $1;
5760 }
5761 }
5762 return "";
5763}
5764
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005765sub getTreeAttr_Op($)
5766{
5767 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5768 {
5769 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5770 return $1;
5771 }
5772 }
5773 return "";
5774}
5775
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005776sub getTreeAttr_Valu($)
5777{
5778 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5779 {
5780 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5781 return $1;
5782 }
5783 }
5784 return "";
5785}
5786
5787sub getTreeAttr_Flds($)
5788{
5789 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5790 {
5791 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5792 return $1;
5793 }
5794 }
5795 return "";
5796}
5797
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005798sub getTreeAttr_Binf($)
5799{
5800 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5801 {
5802 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5803 return $1;
5804 }
5805 }
5806 return "";
5807}
5808
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005809sub getTreeAttr_Args($)
5810{
5811 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5812 {
5813 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005814 return $1;
5815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005816 }
5817 return "";
5818}
5819
5820sub getTreeValue($)
5821{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005822 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5823 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005824 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5825 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005827 }
5828 return "";
5829}
5830
5831sub getTreeAccess($)
5832{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005833 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005834 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005835 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5836 {
5837 my $Access = $1;
5838 if($Access eq "prot") {
5839 return "protected";
5840 }
5841 elsif($Access eq "priv") {
5842 return "private";
5843 }
5844 }
5845 elsif($Info=~/ protected /)
5846 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005847 return "protected";
5848 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005849 elsif($Info=~/ private /)
5850 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005851 return "private";
5852 }
5853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005854 return "public";
5855}
5856
5857sub setFuncAccess($)
5858{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005859 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005860 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005861 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005862 }
5863 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005864 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005865 }
5866}
5867
5868sub setTypeAccess($$)
5869{
5870 my ($TypeId, $TypeAttr) = @_;
5871 my $Access = getTreeAccess($TypeId);
5872 if($Access eq "protected") {
5873 $TypeAttr->{"Protected"} = 1;
5874 }
5875 elsif($Access eq "private") {
5876 $TypeAttr->{"Private"} = 1;
5877 }
5878}
5879
5880sub setFuncKind($)
5881{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005882 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5883 {
5884 if($Info=~/pseudo tmpl/) {
5885 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5886 }
5887 elsif($Info=~/ constructor /) {
5888 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5889 }
5890 elsif($Info=~/ destructor /) {
5891 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005893 }
5894}
5895
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005896sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005898 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5899 {
5900 if($Info=~/spec[ ]*:[ ]*pure /) {
5901 return "PureVirt";
5902 }
5903 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5904 return "Virt";
5905 }
5906 elsif($Info=~/ pure\s+virtual /)
5907 { # support for old GCC versions
5908 return "PureVirt";
5909 }
5910 elsif($Info=~/ virtual /)
5911 { # support for old GCC versions
5912 return "Virt";
5913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005914 }
5915 return "";
5916}
5917
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005918sub getFuncLink($)
5919{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005920 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5921 {
5922 if($Info=~/link[ ]*:[ ]*static /) {
5923 return "Static";
5924 }
5925 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005926 return $1;
5927 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005929 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005930}
5931
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005932sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005934 my ($Symbol, $LibVersion) = @_;
5935 return "" if(not $Symbol or not $LibVersion);
5936 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5937 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005938 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005939 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5940 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5941 }
5942 }
5943 if($NS)
5944 {
5945 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5946 return $NS;
5947 }
5948 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005949 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005950 while($NS=~s/::[^:]+\Z//)
5951 {
5952 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5953 return $NS;
5954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005955 }
5956 }
5957 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005958
5959 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005960}
5961
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005962sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005963{
5964 my ($TypeName, $LibVersion) = @_;
5965 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005966 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005967 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5969 return $NS;
5970 }
5971 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005972 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005973 while($NS=~s/::[^:]+\Z//)
5974 {
5975 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5976 return $NS;
5977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978 }
5979 }
5980 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005981 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005982}
5983
5984sub getNameSpace($)
5985{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005986 my $InfoId = $_[0];
5987 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005988 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005989 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005991 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005992 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005993 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5994 {
5995 my $NameSpace = getTreeStr($1);
5996 if($NameSpace eq "::")
5997 { # global namespace
5998 return "";
5999 }
6000 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6001 $NameSpace = $BaseNameSpace."::".$NameSpace;
6002 }
6003 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6004 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006006 else {
6007 return "";
6008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006009 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006010 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006011 { # inside data type
6012 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6013 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006016 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006017 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018}
6019
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020sub getEnumMembVal($)
6021{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006022 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006023 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006024 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6025 {
6026 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6027 {
6028 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6029 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6030 return getTreeValue($1);
6031 }
6032 else
6033 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6034 return getTreeValue($1);
6035 }
6036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037 }
6038 }
6039 return "";
6040}
6041
6042sub getSize($)
6043{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006044 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6045 {
6046 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6047 return getTreeValue($1);
6048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006049 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051}
6052
6053sub getAlgn($)
6054{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006055 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6056 {
6057 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6058 return $1;
6059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006060 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006061 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062}
6063
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006064sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006065{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006066 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6067 {
6068 if($Info=~/ bitfield /) {
6069 return getSize($_[0]);
6070 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006072 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006073}
6074
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006075sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006076{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006077 if(my $Chan = getTreeAttr_Chan($_[0])) {
6078 return $Chan;
6079 }
6080 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6081 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006082 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006083 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006084}
6085
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006086sub registerHeader($$)
6087{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006088 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006089 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006090 return "";
6091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006092 if(is_abs($Header) and not -f $Header)
6093 { # incorrect absolute path
6094 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006096 if(skipHeader($Header, $LibVersion))
6097 { # skip
6098 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006100 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6101 {
6102 detect_header_includes($Header_Path, $LibVersion);
6103
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006104 if(defined $Tolerance and $Tolerance=~/3/)
6105 { # 3 - skip headers that include non-Linux headers
6106 if($OSgroup ne "windows")
6107 {
6108 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6109 {
6110 if(specificHeader($Inc, "windows")) {
6111 return "";
6112 }
6113 }
6114 }
6115 }
6116
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006117 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6118 { # redirect
6119 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6120 or skipHeader($RHeader_Path, $LibVersion))
6121 { # skip
6122 return "";
6123 }
6124 $Header_Path = $RHeader_Path;
6125 }
6126 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6127 { # skip
6128 return "";
6129 }
6130
6131 if(my $HName = get_filename($Header_Path))
6132 { # register
6133 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6134 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6135 }
6136
6137 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6138 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006139 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006140 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006141 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006142 }
6143
6144 if($CheckHeadersOnly
6145 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6146 { # /usr/include/c++/4.6.1/...
6147 $STDCXX_TESTING = 1;
6148 }
6149
6150 return $Header_Path;
6151 }
6152 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153}
6154
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006155sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006156{
6157 my ($Dir, $WithDeps, $LibVersion) = @_;
6158 $Dir=~s/[\/\\]+\Z//g;
6159 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006160 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006161
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006162 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006163 if($WithDeps)
6164 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006165 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6166 return;
6167 }
6168 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6169 $Mode = "DepsOnly";
6170 }
6171 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006172 else
6173 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006174 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6175 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6176 return;
6177 }
6178 }
6179 $Header_Dependency{$LibVersion}{$Dir} = 1;
6180 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6181 if($Mode eq "DepsOnly")
6182 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006183 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006184 $Header_Dependency{$LibVersion}{$Path} = 1;
6185 }
6186 return;
6187 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006188 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 {
6190 if($WithDeps)
6191 {
6192 my $SubDir = $Path;
6193 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6194 { # register all sub directories
6195 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6196 }
6197 }
6198 next if(is_not_header($Path));
6199 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006200 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006201 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006202 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6203 }
6204 }
6205 if(get_filename($Dir) eq "include")
6206 { # search for "lib/include/" directory
6207 my $LibDir = $Dir;
6208 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006209 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210 }
6211 }
6212}
6213
6214sub parse_redirect($$$)
6215{
6216 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006217 my @Errors = ();
6218 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6219 push(@Errors, $1);
6220 }
6221 my $Redirect = "";
6222 foreach (@Errors)
6223 {
6224 s/\s{2,}/ /g;
6225 if(/(only|must\ include
6226 |update\ to\ include
6227 |replaced\ with
6228 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006229 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006230 {
6231 $Redirect = $2;
6232 last;
6233 }
6234 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6235 {
6236 $Redirect = $2;
6237 last;
6238 }
6239 elsif(/this\ header\ should\ not\ be\ used
6240 |programs\ should\ not\ directly\ include
6241 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6242 |is\ not\ supported\ API\ for\ general\ use
6243 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006244 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006245 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6246 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6247 }
6248 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006249 if($Redirect)
6250 {
6251 $Redirect=~s/\A<//g;
6252 $Redirect=~s/>\Z//g;
6253 }
6254 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006255}
6256
6257sub parse_includes($$)
6258{
6259 my ($Content, $Path) = @_;
6260 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006261 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006262 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006263 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006264 my $Method = substr($Header, 0, 1, "");
6265 substr($Header, length($Header)-1, 1, "");
6266 $Header = path_format($Header, $OSgroup);
6267 if($Method eq "\"" or is_abs($Header))
6268 {
6269 if(-e join_P(get_dirname($Path), $Header))
6270 { # relative path exists
6271 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006272 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006273 else
6274 { # include "..." that doesn't exist is equal to include <...>
6275 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006277 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006278 else {
6279 $Includes{$Header} = 1;
6280 }
6281 }
6282 if($ExtraInfo)
6283 {
6284 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6285 { # FT_FREETYPE_H
6286 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006287 }
6288 }
6289 return \%Includes;
6290}
6291
6292sub ignore_path($)
6293{
6294 my $Path = $_[0];
6295 if($Path=~/\~\Z/)
6296 {# skipping system backup files
6297 return 1;
6298 }
6299 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6300 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6301 return 1;
6302 }
6303 return 0;
6304}
6305
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006306sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006307{
6308 my ($ArrRef, $W) = @_;
6309 return if(length($W)<2);
6310 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6311}
6312
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006313sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006314{
6315 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006316
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006317 $H1=~s/\.[a-z]+\Z//ig;
6318 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006319
6320 my $Hname1 = get_filename($H1);
6321 my $Hname2 = get_filename($H2);
6322 my $HDir1 = get_dirname($H1);
6323 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006324 my $Dirname1 = get_filename($HDir1);
6325 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006326
6327 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6328 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6329
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006330 if($_[0] eq $_[1]
6331 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 return 0;
6333 }
6334 elsif($H1=~/\A\Q$H2\E/) {
6335 return 1;
6336 }
6337 elsif($H2=~/\A\Q$H1\E/) {
6338 return -1;
6339 }
6340 elsif($HDir1=~/\Q$Hname1\E/i
6341 and $HDir2!~/\Q$Hname2\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($HDir2=~/\Q$Hname2\E/i
6346 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006347 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006348 return 1;
6349 }
6350 elsif($Hname1=~/\Q$Dirname1\E/i
6351 and $Hname2!~/\Q$Dirname2\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 }
6355 elsif($Hname2=~/\Q$Dirname2\E/i
6356 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006357 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006358 return 1;
6359 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006360 elsif($Hname1=~/(config|lib|util)/i
6361 and $Hname2!~/(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 elsif($Hname2=~/(config|lib|util)/i
6366 and $Hname1!~/(config|lib|util)/i)
6367 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 return 1;
6369 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006370 else
6371 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006372 my $R1 = checkRelevance($H1);
6373 my $R2 = checkRelevance($H2);
6374 if($R1 and not $R2)
6375 { # libebook/e-book.h
6376 return -1;
6377 }
6378 elsif($R2 and not $R1)
6379 { # libebook/e-book.h
6380 return 1;
6381 }
6382 else
6383 {
6384 return (lc($H1) cmp lc($H2));
6385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006386 }
6387}
6388
6389sub searchForHeaders($)
6390{
6391 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006393 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006394 registerGccHeaders();
6395
6396 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6397 { # c++ standard include paths
6398 registerCppHeaders();
6399 }
6400
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006401 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006402 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6403 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 {
6405 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006406 if($SystemRoot)
6407 {
6408 if(is_abs($Path)) {
6409 $Path = $SystemRoot.$Path;
6410 }
6411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006412 if(not -e $Path) {
6413 exitStatus("Access_Error", "can't access \'$Path\'");
6414 }
6415 elsif(-f $Path) {
6416 exitStatus("Access_Error", "\'$Path\' - not a directory");
6417 }
6418 elsif(-d $Path)
6419 {
6420 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006421 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006422 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6423 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006424 }
6425 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006426 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006427 }
6428 }
6429 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006430 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006431 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6432 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006433
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006434 # registering directories
6435 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6436 {
6437 next if(not -e $Path);
6438 $Path = get_abs_path($Path);
6439 $Path = path_format($Path, $OSgroup);
6440 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006441 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006442 }
6443 elsif(-f $Path)
6444 {
6445 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006446 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006447 and not $LocalIncludes{$Dir})
6448 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006449 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006450 # if(my $OutDir = get_dirname($Dir))
6451 # { # registering the outer directory
6452 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6453 # and not $LocalIncludes{$OutDir}) {
6454 # registerDir($OutDir, 0, $LibVersion);
6455 # }
6456 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 }
6458 }
6459 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006460
6461 # clean memory
6462 %RegisteredDirs = ();
6463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006464 # registering headers
6465 my $Position = 0;
6466 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6467 {
6468 if(is_abs($Dest) and not -e $Dest) {
6469 exitStatus("Access_Error", "can't access \'$Dest\'");
6470 }
6471 $Dest = path_format($Dest, $OSgroup);
6472 if(is_header($Dest, 1, $LibVersion))
6473 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006474 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006475 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6476 }
6477 }
6478 elsif(-d $Dest)
6479 {
6480 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006481 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006482 {
6483 next if(ignore_path($Path));
6484 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006485 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006486 push(@Registered, $HPath);
6487 }
6488 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006489 @Registered = sort {sortHeaders($a, $b)} @Registered;
6490 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006491 foreach my $Path (@Registered) {
6492 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6493 }
6494 }
6495 else {
6496 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6497 }
6498 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006499
6500 if(defined $Tolerance and $Tolerance=~/4/)
6501 { # 4 - skip headers included by others
6502 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6503 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006504 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006505 delete($Registered_Headers{$LibVersion}{$Path});
6506 }
6507 }
6508 }
6509
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006510 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6511 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006512 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006513 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006514 if(is_abs($Header) and not -f $Header) {
6515 exitStatus("Access_Error", "can't access file \'$Header\'");
6516 }
6517 $Header = path_format($Header, $OSgroup);
6518 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6519 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006520 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006521 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006522 }
6523 else {
6524 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006526 }
6527 }
6528 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6529 { # set relative paths (for duplicates)
6530 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6531 { # search for duplicates
6532 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6533 my $Prefix = get_dirname($FirstPath);
6534 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6535 { # detect a shortest distinguishing prefix
6536 my $NewPrefix = $1;
6537 my %Identity = ();
6538 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6539 {
6540 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6541 $Identity{$Path} = $1;
6542 }
6543 }
6544 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006545 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006546 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6547 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6548 }
6549 last;
6550 }
6551 $Prefix = $NewPrefix; # increase prefix
6552 }
6553 }
6554 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006555
6556 # clean memory
6557 %HeaderName_Paths = ();
6558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006559 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6560 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006561 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006562 my ($Pos, $PairPos) = (-1, -1);
6563 my ($Path, $PairPath) = ();
6564 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6565 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6566 foreach my $Header_Path (@Paths)
6567 {
6568 if(get_filename($Header_Path) eq $PairName)
6569 {
6570 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6571 $PairPath = $Header_Path;
6572 }
6573 if(get_filename($Header_Path) eq $HeaderName)
6574 {
6575 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6576 $Path = $Header_Path;
6577 }
6578 }
6579 if($PairPos!=-1 and $Pos!=-1
6580 and int($PairPos)<int($Pos))
6581 {
6582 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6583 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6584 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6585 }
6586 }
6587 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6588 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6589 }
6590}
6591
6592sub detect_real_includes($$)
6593{
6594 my ($AbsPath, $LibVersion) = @_;
6595 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6596 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6597 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6598 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6599 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006600 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6601
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006602 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6603 return () if(not $Path);
6604 open(PREPROC, $Path);
6605 while(<PREPROC>)
6606 {
6607 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6608 {
6609 my $Include = path_format($1, $OSgroup);
6610 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6611 next;
6612 }
6613 if($Include eq $AbsPath) {
6614 next;
6615 }
6616 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6617 }
6618 }
6619 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006620 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6621}
6622
6623sub detect_header_includes($$)
6624{
6625 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006626 return if(not $LibVersion or not $Path);
6627 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6628 return;
6629 }
6630 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6631
6632 if(not -e $Path) {
6633 return;
6634 }
6635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006636 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006637 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6638 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006639 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006640 {
6641 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006642 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006643 }
6644 if($RedirectPath ne $Path) {
6645 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6646 }
6647 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006648 else
6649 { # can't find
6650 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006652 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006653 if(my $Inc = parse_includes($Content, $Path))
6654 {
6655 foreach my $Include (keys(%{$Inc}))
6656 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006657 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006658
6659 if(defined $Tolerance and $Tolerance=~/4/)
6660 {
6661 if(my $HPath = identifyHeader($Include, $LibVersion))
6662 {
6663 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6664 }
6665 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006668}
6669
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006670sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006671{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 my $Path = $_[0];
6673 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006674 if($OStarget eq "symbian")
6675 {
6676 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6677 { # epoc32/include/libc/{stdio, ...}.h
6678 return 1;
6679 }
6680 }
6681 else
6682 {
6683 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6684 { # /usr/include/{stdio, ...}.h
6685 return 1;
6686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006688 return 0;
6689}
6690
6691sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006692{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006693 my $Dir = $_[0];
6694 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006695 if($OStarget eq "symbian")
6696 {
6697 if(get_filename($OutDir) eq "libc"
6698 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6699 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6700 return 1;
6701 }
6702 }
6703 else
6704 { # linux
6705 if($OutDir eq "/usr/include"
6706 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6707 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6708 return 1;
6709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006710 }
6711 return 0;
6712}
6713
6714sub detect_recursive_includes($$)
6715{
6716 my ($AbsPath, $LibVersion) = @_;
6717 return () if(not $AbsPath);
6718 if(isCyclical(\@RecurInclude, $AbsPath)) {
6719 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6720 }
6721 my ($AbsDir, $Name) = separate_path($AbsPath);
6722 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006723 { # system GLIBC internals
6724 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 }
6726 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6727 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6728 }
6729 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006730
6731 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6732 { # skip /usr/include/c++/*/ headers
6733 return () if(not $ExtraInfo);
6734 }
6735
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006737 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006738 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006739 { # check "real" (non-"model") include paths
6740 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6741 pop(@RecurInclude);
6742 return @Paths;
6743 }
6744 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6745 detect_header_includes($AbsPath, $LibVersion);
6746 }
6747 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6748 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006749 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006750 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006751 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006752 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006753 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006754 if(-f $Candidate) {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03006755 $HPath = realpath_F($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006756 }
6757 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006758 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006759 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006760 { # search for the nearest header
6761 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006762 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006763 if(-f $Candidate) {
6764 $HPath = $Candidate;
6765 }
6766 }
6767 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006768 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006769 }
6770 next if(not $HPath);
6771 if($HPath eq $AbsPath) {
6772 next;
6773 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006774
6775 if($Debug)
6776 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006777# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6778# {
6779# print STDERR "$AbsPath -> $HPath\n";
6780# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006781 }
6782
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006783 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6784 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006785 { # only include <...>, skip include "..." prefixes
6786 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6787 }
6788 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6789 {
6790 if($IncPath eq $AbsPath) {
6791 next;
6792 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006793 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6794 if($RIncType==-1)
6795 { # include "..."
6796 $RIncType = $IncType;
6797 }
6798 elsif($RIncType==2)
6799 {
6800 if($IncType!=-1) {
6801 $RIncType = $IncType;
6802 }
6803 }
6804 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006805 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6806 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6807 }
6808 }
6809 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6810 {
6811 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6812 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6813 { # distinguish math.h from glibc and math.h from the tested library
6814 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6815 last;
6816 }
6817 }
6818 }
6819 pop(@RecurInclude);
6820 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6821}
6822
6823sub find_in_framework($$$)
6824{
6825 my ($Header, $Framework, $LibVersion) = @_;
6826 return "" if(not $Header or not $Framework or not $LibVersion);
6827 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6828 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6829 }
6830 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6831 {
6832 if(get_filename($Dependency) eq $Framework
6833 and -f get_dirname($Dependency)."/".$Header) {
6834 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6835 }
6836 }
6837 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6838}
6839
6840sub find_in_defaults($)
6841{
6842 my $Header = $_[0];
6843 return "" if(not $Header);
6844 if(defined $Cache{"find_in_defaults"}{$Header}) {
6845 return $Cache{"find_in_defaults"}{$Header};
6846 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006847 foreach my $Dir (@DefaultIncPaths,
6848 @DefaultGccPaths,
6849 @DefaultCppPaths,
6850 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006851 {
6852 next if(not $Dir);
6853 if(-f $Dir."/".$Header) {
6854 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6855 }
6856 }
6857 return ($Cache{"find_in_defaults"}{$Header}="");
6858}
6859
6860sub cmp_paths($$)
6861{
6862 my ($Path1, $Path2) = @_;
6863 my @Parts1 = split(/[\/\\]/, $Path1);
6864 my @Parts2 = split(/[\/\\]/, $Path2);
6865 foreach my $Num (0 .. $#Parts1)
6866 {
6867 my $Part1 = $Parts1[$Num];
6868 my $Part2 = $Parts2[$Num];
6869 if($GlibcDir{$Part1}
6870 and not $GlibcDir{$Part2}) {
6871 return 1;
6872 }
6873 elsif($GlibcDir{$Part2}
6874 and not $GlibcDir{$Part1}) {
6875 return -1;
6876 }
6877 elsif($Part1=~/glib/
6878 and $Part2!~/glib/) {
6879 return 1;
6880 }
6881 elsif($Part1!~/glib/
6882 and $Part2=~/glib/) {
6883 return -1;
6884 }
6885 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6886 return $CmpRes;
6887 }
6888 }
6889 return 0;
6890}
6891
6892sub checkRelevance($)
6893{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006894 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006897 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006898 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006899 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006900
6901 my $Name = lc(get_filename($Path));
6902 my $Dir = lc(get_dirname($Path));
6903
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006904 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006905
6906 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006907 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006908 my $Len = length($Token);
6909 next if($Len<=1);
6910 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6911 { # include/evolution-data-server-1.4/libebook/e-book.h
6912 return 1;
6913 }
6914 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006915 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006916 return 1;
6917 }
6918 }
6919 return 0;
6920}
6921
6922sub checkFamily(@)
6923{
6924 my @Paths = @_;
6925 return 1 if($#Paths<=0);
6926 my %Prefix = ();
6927 foreach my $Path (@Paths)
6928 {
6929 if($SystemRoot) {
6930 $Path = cut_path_prefix($Path, $SystemRoot);
6931 }
6932 if(my $Dir = get_dirname($Path))
6933 {
6934 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6935 $Prefix{$Dir} += 1;
6936 $Prefix{get_dirname($Dir)} += 1;
6937 }
6938 }
6939 foreach (sort keys(%Prefix))
6940 {
6941 if(get_depth($_)>=3
6942 and $Prefix{$_}==$#Paths+1) {
6943 return 1;
6944 }
6945 }
6946 return 0;
6947}
6948
6949sub isAcceptable($$$)
6950{
6951 my ($Header, $Candidate, $LibVersion) = @_;
6952 my $HName = get_filename($Header);
6953 if(get_dirname($Header))
6954 { # with prefix
6955 return 1;
6956 }
6957 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6958 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6959 return 1;
6960 }
6961 if(checkRelevance($Candidate))
6962 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6963 return 1;
6964 }
6965 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6966 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6967 # /usr/include/qt4/Qt/qsslconfiguration.h
6968 return 1;
6969 }
6970 if($OStarget eq "symbian")
6971 {
6972 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6973 return 1;
6974 }
6975 }
6976 return 0;
6977}
6978
6979sub isRelevant($$$)
6980{ # disallow to search for "abstract" headers in too deep directories
6981 my ($Header, $Candidate, $LibVersion) = @_;
6982 my $HName = get_filename($Header);
6983 if($OStarget eq "symbian")
6984 {
6985 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6986 return 0;
6987 }
6988 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006989 if($OStarget ne "bsd")
6990 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006991 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6992 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6993 return 0;
6994 }
6995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006996 if($OStarget ne "windows")
6997 {
6998 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6999 { # skip /usr/include/wine/msvcrt
7000 return 0;
7001 }
7002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007003 if(not get_dirname($Header)
7004 and $Candidate=~/[\/\\]wx[\/\\]/)
7005 { # do NOT search in system /wx/ directory
7006 # for headers without a prefix: sstream.h
7007 return 0;
7008 }
7009 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7010 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7011 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7012 return 0;
7013 }
7014 if($Candidate=~/[\/\\]asm-/
7015 and (my $Arch = getArch($LibVersion)) ne "unknown")
7016 { # arch-specific header files
7017 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7018 {# skip ../asm-arm/ if using x86 architecture
7019 return 0;
7020 }
7021 }
7022 my @Candidates = getSystemHeaders($HName, $LibVersion);
7023 if($#Candidates==1)
7024 { # unique header
7025 return 1;
7026 }
7027 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7028 if($#SCandidates==1)
7029 { # unique name
7030 return 1;
7031 }
7032 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7033 if(get_depth($Candidate)-$SystemDepth>=5)
7034 { # abstract headers in too deep directories
7035 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7036 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7037 return 0;
7038 }
7039 }
7040 if($Header eq "parser.h"
7041 and $Candidate!~/\/libxml2\//)
7042 { # select parser.h from xml2 library
7043 return 0;
7044 }
7045 if(not get_dirname($Header)
7046 and keys(%{$SystemHeaders{$HName}})>=3)
7047 { # many headers with the same name
7048 # like thread.h included without a prefix
7049 if(not checkFamily(@Candidates)) {
7050 return 0;
7051 }
7052 }
7053 return 1;
7054}
7055
7056sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007057{ # cache function
7058 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7059 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7060 }
7061 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7062}
7063
7064sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007065{
7066 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007067 if(-f $Header) {
7068 return $Header;
7069 }
7070 if(is_abs($Header) and not -f $Header)
7071 { # incorrect absolute path
7072 return "";
7073 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007074 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007075 { # too abstract configuration headers
7076 return "";
7077 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007078 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007079 if($OSgroup ne "windows")
7080 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007081 if(defined $WinHeaders{lc($HName)}
7082 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007083 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007084 return "";
7085 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007086 }
7087 if($OSgroup ne "macos")
7088 {
7089 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007090 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091 return "";
7092 }
7093 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007094
7095 if(defined $ObsoleteHeaders{$HName})
7096 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007097 return "";
7098 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007099 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7100 {
7101 if(defined $AlienHeaders{$HName}
7102 or defined $AlienHeaders{$Header})
7103 { # alien headers from other systems
7104 return "";
7105 }
7106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007107
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007108 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007109 { # search in default paths
7110 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007111 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007112 }
7113 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007114 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007115 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007116 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007117 }
7118 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7119 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7120 {
7121 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007122 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007123 }
7124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007125 # error
7126 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127}
7128
7129sub getSystemHeaders($$)
7130{
7131 my ($Header, $LibVersion) = @_;
7132 my @Candidates = ();
7133 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7134 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007135 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007136 next;
7137 }
7138 push(@Candidates, $Candidate);
7139 }
7140 return @Candidates;
7141}
7142
7143sub cut_path_prefix($$)
7144{
7145 my ($Path, $Prefix) = @_;
7146 return $Path if(not $Prefix);
7147 $Prefix=~s/[\/\\]+\Z//;
7148 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7149 return $Path;
7150}
7151
7152sub is_default_include_dir($)
7153{
7154 my $Dir = $_[0];
7155 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007156 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007157}
7158
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007159sub identifyHeader($$)
7160{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007161 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007162 if(not $Header) {
7163 return "";
7164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007165 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007166 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7167 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007169 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170}
7171
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007172sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007173{ # search for header by absolute path, relative path or name
7174 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007175 if(-f $Header)
7176 { # it's relative or absolute path
7177 return get_abs_path($Header);
7178 }
7179 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7180 and my $HeaderDir = find_in_defaults($Header))
7181 { # search for libc headers in the /usr/include
7182 # for non-libc target library before searching
7183 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007184 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185 }
7186 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7187 { # search in the target library paths
7188 return $Path;
7189 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007190 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191 { # search in the internal GCC include paths
7192 return $DefaultGccHeader{$Header};
7193 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007194 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007195 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007196 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007198 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007199 { # search in the default G++ include paths
7200 return $DefaultCppHeader{$Header};
7201 }
7202 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7203 { # search everywhere in the system
7204 return $AnyPath;
7205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007206 elsif($OSgroup eq "macos")
7207 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7208 if(my $Dir = get_dirname($Header))
7209 {
7210 my $RelPath = "Headers\/".get_filename($Header);
7211 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007212 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007213 }
7214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007216 # cannot find anything
7217 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007218}
7219
7220sub getLocation($)
7221{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007222 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7223 {
7224 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007225 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007228 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229}
7230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007231sub getNameByInfo($)
7232{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007233 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007234 {
7235 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7236 {
7237 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7238 {
7239 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7240 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007241 my $Str = $1;
7242 if($CppMode{$Version}
7243 and $Str=~/\Ac99_(.+)\Z/)
7244 {
7245 if($CppKeywords_A{$1}) {
7246 $Str=$1;
7247 }
7248 }
7249 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007250 }
7251 }
7252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007254 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255}
7256
7257sub getTreeStr($)
7258{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007259 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007260 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007261 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7262 {
7263 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007264 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007265 and $Str=~/\Ac99_(.+)\Z/)
7266 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007267 if($CppKeywords_A{$1}) {
7268 $Str=$1;
7269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007270 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007271 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007273 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007274 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007275}
7276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007277sub getFuncShortName($)
7278{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007279 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007280 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007281 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007282 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007283 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007284 {
7285 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7286 {
7287 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7288 return "operator ".$RName;
7289 }
7290 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007291 }
7292 else
7293 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007294 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7295 {
7296 if(my $Ind = $Operator_Indication{$1}) {
7297 return "operator".$Ind;
7298 }
7299 elsif(not $UnknownOperator{$1})
7300 {
7301 printMsg("WARNING", "unknown operator $1");
7302 $UnknownOperator{$1} = 1;
7303 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007304 }
7305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 }
7307 else
7308 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007309 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7310 return getTreeStr($1);
7311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312 }
7313 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007314 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007315}
7316
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317sub getFuncReturn($)
7318{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007319 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7320 {
7321 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7322 {
7323 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7324 return $1;
7325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007326 }
7327 }
7328 return "";
7329}
7330
7331sub getFuncOrig($)
7332{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007333 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7334 {
7335 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7336 return $1;
7337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007338 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007339 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007340}
7341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007342sub unmangleArray(@)
7343{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007344 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007345 { # MSVC mangling
7346 my $UndNameCmd = get_CmdPath("undname");
7347 if(not $UndNameCmd) {
7348 exitStatus("Not_Found", "can't find \"undname\"");
7349 }
7350 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007351 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007352 }
7353 else
7354 { # GCC mangling
7355 my $CppFiltCmd = get_CmdPath("c++filt");
7356 if(not $CppFiltCmd) {
7357 exitStatus("Not_Found", "can't find c++filt in PATH");
7358 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007359 if(not defined $CPPFILT_SUPPORT_FILE)
7360 {
7361 my $Info = `$CppFiltCmd -h 2>&1`;
7362 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7363 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007364 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007365 if($CPPFILT_SUPPORT_FILE)
7366 { # new versions of c++filt can take a file
7367 if($#_>$MAX_CPPFILT_FILE_SIZE)
7368 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7369 # this is fixed in the oncoming version of Binutils
7370 my @Half = splice(@_, 0, ($#_+1)/2);
7371 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007372 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007373 else
7374 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007375 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7376 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7377 if($?==139)
7378 { # segmentation fault
7379 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7380 }
7381 return split(/\n/, $Res);
7382 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007383 }
7384 else
7385 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007386 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7387 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 my @Half = splice(@_, 0, ($#_+1)/2);
7389 return (unmangleArray(@Half), unmangleArray(@_))
7390 }
7391 else
7392 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007393 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007394 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7395 if($?==139)
7396 { # segmentation fault
7397 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7398 }
7399 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 }
7401 }
7402 }
7403}
7404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405sub get_ChargeLevel($$)
7406{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007407 my ($Symbol, $LibVersion) = @_;
7408 return "" if($Symbol!~/\A(_Z|\?)/);
7409 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7410 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007412 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007414 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 return "[in-charge]";
7416 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007417 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007418 return "[not-in-charge]";
7419 }
7420 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007421 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007423 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007424 return "[in-charge]";
7425 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007426 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007427 return "[not-in-charge]";
7428 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007429 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430 return "[in-charge-deleting]";
7431 }
7432 }
7433 }
7434 else
7435 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007436 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007437 return "[in-charge]";
7438 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007439 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007440 return "[not-in-charge]";
7441 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007442 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007443 return "[in-charge]";
7444 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007445 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446 return "[not-in-charge]";
7447 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007448 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449 return "[in-charge-deleting]";
7450 }
7451 }
7452 return "";
7453}
7454
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007455sub get_Signature_M($$)
7456{
7457 my ($Symbol, $LibVersion) = @_;
7458 my $Signature_M = $tr_name{$Symbol};
7459 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7460 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007461 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007462 }
7463 return $Signature_M;
7464}
7465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466sub get_Signature($$)
7467{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007468 my ($Symbol, $LibVersion) = @_;
7469 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7470 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007472 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007473 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007474
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007475 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007476
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007477 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007479 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7480 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007481 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7482 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007483
7484 if(index($Symbol, "_ZTV")==0) {
7485 return "vtable for $ClassName [data]";
7486 }
7487
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007488 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007489 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7490 $Signature .= "~";
7491 }
7492 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007493 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007494 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007495 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007496 }
7497 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007498 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007500 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7501 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007502 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007503 else
7504 {
7505 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 }
7507 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007508 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007509 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007510 if($Pos eq "") {
7511 next;
7512 }
7513
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007514 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007515 if(not $ParamTypeId) {
7516 next;
7517 }
7518
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007519 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 if(not $ParamTypeName) {
7521 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7522 }
7523 foreach my $Typedef (keys(%ChangedTypedef))
7524 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007525 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7526 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007529 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7530 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007531 if($ParamName eq "this"
7532 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007533 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007534 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007535 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007536 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 }
7538 else {
7539 push(@ParamArray, $ParamTypeName);
7540 }
7541 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007542 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7543 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007544 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007545 }
7546 else
7547 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007548 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007549 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007550 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007551 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007552 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007553 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7554 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007555 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007556 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007557 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7558 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007559 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007560 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007561 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7562 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007563 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007564 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565 }
7566 }
7567 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007568 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007569 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007570 }
7571 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007572 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007573 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007574 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575}
7576
7577sub create_member_decl($$)
7578{
7579 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007580 if($TName=~/\([\*]+\)/)
7581 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7583 return $TName;
7584 }
7585 else
7586 {
7587 my @ArraySizes = ();
7588 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7589 push(@ArraySizes, $1);
7590 }
7591 return $TName." ".$Member.join("", @ArraySizes);
7592 }
7593}
7594
7595sub getFuncType($)
7596{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007597 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7598 {
7599 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7600 {
7601 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7602 {
7603 if($Type eq "method_type") {
7604 return "Method";
7605 }
7606 elsif($Type eq "function_type") {
7607 return "Function";
7608 }
7609 else {
7610 return "Other";
7611 }
7612 }
7613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007614 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007615 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007616}
7617
7618sub getFuncTypeId($)
7619{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007620 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7621 {
7622 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7623 return $1;
7624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007625 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007626 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007627}
7628
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007629sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007630{ # "._N" or "$_N" in older GCC versions
7631 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007632}
7633
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007634sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007635{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007636 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7637 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638 }
7639
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007640 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007641
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007642 if($_[1] ne "S")
7643 {
7644 $N=~s/\A[ ]+//g;
7645 $N=~s/[ ]+\Z//g;
7646 $N=~s/[ ]{2,}/ /g;
7647 }
7648
7649 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007650
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007651 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7652
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007653 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007654
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007655 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7656 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007657
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007658 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007659
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007660 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007661
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007662 if($_[1] eq "S")
7663 {
7664 if(index($N, "operator")!=-1) {
7665 $N=~s/\b(operator[ ]*)> >/$1>>/;
7666 }
7667 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007668
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007669 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007670
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007671 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007672}
7673
7674sub get_HeaderDeps($$)
7675{
7676 my ($AbsPath, $LibVersion) = @_;
7677 return () if(not $AbsPath or not $LibVersion);
7678 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7679 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7680 }
7681 my %IncDir = ();
7682 detect_recursive_includes($AbsPath, $LibVersion);
7683 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7684 {
7685 next if(not $HeaderPath);
7686 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7687 my $Dir = get_dirname($HeaderPath);
7688 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7689 {
7690 my $Dep = $Dir;
7691 if($Prefix)
7692 {
7693 if($OSgroup eq "windows")
7694 { # case insensitive seach on windows
7695 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7696 next;
7697 }
7698 }
7699 elsif($OSgroup eq "macos")
7700 { # seach in frameworks
7701 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7702 {
7703 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7704 {# frameworks
7705 my ($HFramework, $HName) = ($1, $2);
7706 $Dep = $HFramework;
7707 }
7708 else
7709 {# mismatch
7710 next;
7711 }
7712 }
7713 }
7714 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7715 { # Linux, FreeBSD
7716 next;
7717 }
7718 }
7719 if(not $Dep)
7720 { # nothing to include
7721 next;
7722 }
7723 if(is_default_include_dir($Dep))
7724 { # included by the compiler
7725 next;
7726 }
7727 if(get_depth($Dep)==1)
7728 { # too short
7729 next;
7730 }
7731 if(isLibcDir($Dep))
7732 { # do NOT include /usr/include/{sys,bits}
7733 next;
7734 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007735 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007736 }
7737 }
7738 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7739 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7740}
7741
7742sub sortIncPaths($$)
7743{
7744 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007745 if(not $ArrRef or $#{$ArrRef}<0) {
7746 return $ArrRef;
7747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007748 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7749 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007750 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007751 return $ArrRef;
7752}
7753
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007754sub sortDeps($$$)
7755{
7756 if($Header_Dependency{$_[2]}{$_[0]}
7757 and not $Header_Dependency{$_[2]}{$_[1]}) {
7758 return 1;
7759 }
7760 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7761 and $Header_Dependency{$_[2]}{$_[1]}) {
7762 return -1;
7763 }
7764 return 0;
7765}
7766
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007767sub join_P($$)
7768{
7769 my $S = "/";
7770 if($OSgroup eq "windows") {
7771 $S = "\\";
7772 }
7773 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007774}
7775
7776sub get_namespace_additions($)
7777{
7778 my $NameSpaces = $_[0];
7779 my ($Additions, $AddNameSpaceId) = ("", 1);
7780 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7781 {
7782 next if($SkipNameSpaces{$Version}{$NS});
7783 next if(not $NS or $NameSpaces->{$NS}==-1);
7784 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7785 next if($NS=~/\A__/i);
7786 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007787 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007788 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7789 my @NS_Parts = split(/::/, $NS);
7790 next if($#NS_Parts==-1);
7791 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7792 foreach my $NS_Part (@NS_Parts)
7793 {
7794 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7795 $TypeDecl_Suffix .= "}";
7796 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007797 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007798 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7799 $Additions.=" $TypeDecl\n $FuncDecl\n";
7800 $AddNameSpaceId+=1;
7801 }
7802 return $Additions;
7803}
7804
7805sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007806{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007807 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007808 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007809 if($Fmt eq "windows")
7810 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007811 $Path=~s/\//\\/g;
7812 $Path=lc($Path);
7813 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007814 else
7815 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007816 $Path=~s/\\/\//g;
7817 }
7818 return $Path;
7819}
7820
7821sub inc_opt($$)
7822{
7823 my ($Path, $Style) = @_;
7824 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007825 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007826 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007827 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007828 return "-I\"".path_format($Path, "unix")."\"";
7829 }
7830 elsif($OSgroup eq "macos"
7831 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007832 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007833 return "-F".esc(get_dirname($Path));
7834 }
7835 else {
7836 return "-I".esc($Path);
7837 }
7838 }
7839 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007840 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007841 }
7842 return "";
7843}
7844
7845sub platformSpecs($)
7846{
7847 my $LibVersion = $_[0];
7848 my $Arch = getArch($LibVersion);
7849 if($OStarget eq "symbian")
7850 { # options for GCCE compiler
7851 my %Symbian_Opts = map {$_=>1} (
7852 "-D__GCCE__",
7853 "-DUNICODE",
7854 "-fexceptions",
7855 "-D__SYMBIAN32__",
7856 "-D__MARM_INTERWORK__",
7857 "-D_UNICODE",
7858 "-D__S60_50__",
7859 "-D__S60_3X__",
7860 "-D__SERIES60_3X__",
7861 "-D__EPOC32__",
7862 "-D__MARM__",
7863 "-D__EABI__",
7864 "-D__MARM_ARMV5__",
7865 "-D__SUPPORT_CPP_EXCEPTIONS__",
7866 "-march=armv5t",
7867 "-mapcs",
7868 "-mthumb-interwork",
7869 "-DEKA2",
7870 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7871 );
7872 return join(" ", keys(%Symbian_Opts));
7873 }
7874 elsif($OSgroup eq "windows"
7875 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7876 { # add options to MinGW compiler
7877 # to simulate the MSVC compiler
7878 my %MinGW_Opts = map {$_=>1} (
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007879 "-D__unaligned=\" \"",
7880 "-D__nullptr=\"nullptr\"",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007881 "-D_WIN32",
7882 "-D_STDCALL_SUPPORTED",
7883 "-D__int64=\"long long\"",
7884 "-D__int32=int",
7885 "-D__int16=short",
7886 "-D__int8=char",
7887 "-D__possibly_notnullterminated=\" \"",
7888 "-D__nullterminated=\" \"",
7889 "-D__nullnullterminated=\" \"",
7890 "-D__w64=\" \"",
7891 "-D__ptr32=\" \"",
7892 "-D__ptr64=\" \"",
7893 "-D__forceinline=inline",
7894 "-D__inline=inline",
7895 "-D__uuidof(x)=IID()",
7896 "-D__try=",
7897 "-D__except(x)=",
7898 "-D__declspec(x)=__attribute__((x))",
7899 "-D__pragma(x)=",
7900 "-D_inline=inline",
7901 "-D__forceinline=__inline",
7902 "-D__stdcall=__attribute__((__stdcall__))",
7903 "-D__cdecl=__attribute__((__cdecl__))",
7904 "-D__fastcall=__attribute__((__fastcall__))",
7905 "-D__thiscall=__attribute__((__thiscall__))",
7906 "-D_stdcall=__attribute__((__stdcall__))",
7907 "-D_cdecl=__attribute__((__cdecl__))",
7908 "-D_fastcall=__attribute__((__fastcall__))",
7909 "-D_thiscall=__attribute__((__thiscall__))",
7910 "-DSHSTDAPI_(x)=x",
7911 "-D_MSC_EXTENSIONS",
7912 "-DSECURITY_WIN32",
7913 "-D_MSC_VER=1500",
7914 "-D_USE_DECLSPECS_FOR_SAL",
7915 "-D__noop=\" \"",
7916 "-DDECLSPEC_DEPRECATED=\" \"",
7917 "-D__builtin_alignof(x)=__alignof__(x)",
7918 "-DSORTPP_PASS");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007919 if($Arch eq "x86")
7920 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007921 $MinGW_Opts{"-D_M_IX86=300"}=1;
7922 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007923 elsif($Arch eq "x86_64")
7924 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007925 $MinGW_Opts{"-D_M_AMD64=300"}=1;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +03007926 $MinGW_Opts{"-D_M_X64=300"}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007927 }
7928 elsif($Arch eq "ia64") {
7929 $MinGW_Opts{"-D_M_IA64=300"}=1;
7930 }
7931 return join(" ", keys(%MinGW_Opts));
7932 }
7933 return "";
7934}
7935
7936my %C_Structure = map {$_=>1} (
7937# FIXME: Can't separate union and struct data types before dumping,
7938# so it sometimes cause compilation errors for unknown reason
7939# when trying to declare TYPE* tmp_add_class_N
7940# This is a list of such structures + list of other C structures
7941 "sigval",
7942 "sigevent",
7943 "sigaction",
7944 "sigvec",
7945 "sigstack",
7946 "timeval",
7947 "timezone",
7948 "rusage",
7949 "rlimit",
7950 "wait",
7951 "flock",
7952 "stat",
7953 "_stat",
7954 "stat32",
7955 "_stat32",
7956 "stat64",
7957 "_stat64",
7958 "_stati64",
7959 "if_nameindex",
7960 "usb_device",
7961 "sigaltstack",
7962 "sysinfo",
7963 "timeLocale",
7964 "tcp_debug",
7965 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007966 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007967 "timespec",
7968 "random_data",
7969 "drand48_data",
7970 "_IO_marker",
7971 "_IO_FILE",
7972 "lconv",
7973 "sched_param",
7974 "tm",
7975 "itimerspec",
7976 "_pthread_cleanup_buffer",
7977 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007978 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007979 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007980 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007981 "sigcontext",
7982 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007983 # Mac
7984 "_timex",
7985 "_class_t",
7986 "_category_t",
7987 "_class_ro_t",
7988 "_protocol_t",
7989 "_message_ref_t",
7990 "_super_message_ref_t",
7991 "_ivar_t",
7992 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993);
7994
7995sub getCompileCmd($$$)
7996{
7997 my ($Path, $Opt, $Inc) = @_;
7998 my $GccCall = $GCC_PATH;
7999 if($Opt) {
8000 $GccCall .= " ".$Opt;
8001 }
8002 $GccCall .= " -x ";
8003 if($OSgroup eq "macos") {
8004 $GccCall .= "objective-";
8005 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008006
8007 if($EMERGENCY_MODE_48)
8008 { # workaround for GCC 4.8 (C only)
8009 $GccCall .= "c++";
8010 }
8011 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008012 { # compile as "C++" header
8013 # to obtain complete dump using GCC 4.0
8014 $GccCall .= "c++-header";
8015 }
8016 else
8017 { # compile as "C++" source
8018 # GCC 3.3 cannot compile headers
8019 $GccCall .= "c++";
8020 }
8021 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008022 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008023 $GccCall .= " ".$Opts;
8024 }
8025 # allow extra qualifications
8026 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008027 $GccCall .= " -fpermissive";
8028 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008029 if($NoStdInc)
8030 {
8031 $GccCall .= " -nostdinc";
8032 $GccCall .= " -nostdinc++";
8033 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008034 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008035 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008036 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008037 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008038 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008039 if($Inc)
8040 { # include paths
8041 $GccCall .= " ".$Inc;
8042 }
8043 return $GccCall;
8044}
8045
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008046sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008047{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008048 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008049 my %HeaderElems = (
8050 # Types
8051 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008052 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008053 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8054 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008055 "time.h" => ["time_t"],
8056 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008057 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8058 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008059 "stdbool.h" => ["_Bool"],
8060 "rpc/xdr.h" => ["bool_t"],
8061 "in_systm.h" => ["n_long", "n_short"],
8062 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008063 "arpa/inet.h" => ["fw_src", "ip_src"],
8064 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008065 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008066 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008067 );
8068 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008069 foreach (keys(%HeaderElems))
8070 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008071 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008072 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008073 }
8074 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008075 my %Types = ();
8076 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8077 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008078 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008079 }
8080 if(keys(%Types))
8081 {
8082 my %AddHeaders = ();
8083 foreach my $Type (keys(%Types))
8084 {
8085 if(my $Header = $AutoPreamble{$Type})
8086 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008087 if(my $Path = identifyHeader($Header, $LibVersion))
8088 {
8089 if(skipHeader($Path, $LibVersion)) {
8090 next;
8091 }
8092 $Path = path_format($Path, $OSgroup);
8093 $AddHeaders{$Path}{"Type"} = $Type;
8094 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008095 }
8096 }
8097 }
8098 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008099 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008100 }
8101 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008102 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008103}
8104
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008105sub checkCTags($)
8106{
8107 my $Path = $_[0];
8108 if(not $Path) {
8109 return;
8110 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008111 my $CTags = undef;
8112
8113 if($OSgroup eq "bsd")
8114 { # use ectags on BSD
8115 $CTags = get_CmdPath("ectags");
8116 if(not $CTags) {
8117 printMsg("WARNING", "can't find \'ectags\' program");
8118 }
8119 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008120 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008121 $CTags = get_CmdPath("ctags");
8122 }
8123 if(not $CTags)
8124 {
8125 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008126 return;
8127 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008128
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008129 if($OSgroup ne "linux")
8130 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008131 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8132 if($Info!~/exuberant/i)
8133 {
8134 printMsg("WARNING", "incompatible version of \'ctags\' program");
8135 return;
8136 }
8137 }
8138
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008139 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008140 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008141 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008142 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008143 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008144 open(CTAGS, "<", $Out);
8145 while(my $Line = <CTAGS>)
8146 {
8147 chomp($Line);
8148 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008149 if(defined $Intrinsic_Keywords{$Name})
8150 { # noise
8151 next;
8152 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008153 if($Type eq "n")
8154 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008155 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008156 next;
8157 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008158 if(index($Scpe, "struct:")==0) {
8159 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008160 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008161 if(index($Scpe, "namespace:")==0)
8162 {
8163 if($Scpe=~s/\Anamespace://) {
8164 $Name = $Scpe."::".$Name;
8165 }
8166 }
8167 $TUnit_NameSpaces{$Version}{$Name} = 1;
8168 }
8169 elsif($Type eq "p")
8170 {
8171 if(not $Scpe or index($Scpe, "namespace:")==0) {
8172 $TUnit_Funcs{$Version}{$Name} = 1;
8173 }
8174 }
8175 elsif($Type eq "x")
8176 {
8177 if(not $Scpe or index($Scpe, "namespace:")==0) {
8178 $TUnit_Vars{$Version}{$Name} = 1;
8179 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008180 }
8181 }
8182 close(CTAGS);
8183}
8184
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008185sub preChange($$)
8186{
8187 my ($HeaderPath, $IncStr) = @_;
8188
8189 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8190 my $Content = undef;
8191
8192 if($OStarget eq "windows"
8193 and get_dumpmachine($GCC_PATH)=~/mingw/i
8194 and $MinGWMode{$Version}!=-1)
8195 { # modify headers to compile by MinGW
8196 if(not $Content)
8197 { # preprocessing
8198 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8199 }
8200 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8201 { # __asm { ... }
8202 $MinGWMode{$Version}=1;
8203 }
8204 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8205 { # comments after preprocessing
8206 $MinGWMode{$Version}=1;
8207 }
8208 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8209 { # 0xffui8
8210 $MinGWMode{$Version}=1;
8211 }
8212
8213 if($MinGWMode{$Version}) {
8214 printMsg("INFO", "Using MinGW compatibility mode");
8215 }
8216 }
8217
8218 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8219 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8220 { # rename C++ keywords in C code
8221 # disable this code by -cpp-compatible option
8222 if(not $Content)
8223 { # preprocessing
8224 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8225 }
8226 my $RegExp_C = join("|", keys(%CppKeywords_C));
8227 my $RegExp_F = join("|", keys(%CppKeywords_F));
8228 my $RegExp_O = join("|", keys(%CppKeywords_O));
8229
8230 my $Detected = undef;
8231
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008232 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 +04008233 { # MATCH:
8234 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008235 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008236 # unsigned private: 8;
8237 # DO NOT MATCH:
8238 # #pragma GCC visibility push(default)
8239 $CppMode{$Version} = 1;
8240 $Detected = "$1$2$3$4" if(not defined $Detected);
8241 }
8242 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8243 { # MATCH:
8244 # int delete(...);
8245 # int explicit(...);
8246 # DO NOT MATCH:
8247 # void operator delete(...)
8248 $CppMode{$Version} = 1;
8249 $Detected = "$1$2$3" if(not defined $Detected);
8250 }
8251 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8252 { # MATCH:
8253 # int bool;
8254 # DO NOT MATCH:
8255 # bool X;
8256 # return *this;
8257 # throw;
8258 $CppMode{$Version} = 1;
8259 $Detected = "$1$2$3" if(not defined $Detected);
8260 }
8261 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8262 { # MATCH:
8263 # int operator(...);
8264 # DO NOT MATCH:
8265 # int operator()(...);
8266 $CppMode{$Version} = 1;
8267 $Detected = "$1$2$3" if(not defined $Detected);
8268 }
8269 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8270 { # MATCH:
8271 # int foo(int operator);
8272 # int foo(int operator, int other);
8273 # DO NOT MATCH:
8274 # int operator,(...);
8275 $CppMode{$Version} = 1;
8276 $Detected = "$1$2$3" if(not defined $Detected);
8277 }
8278 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8279 { # MATCH:
8280 # int foo(gboolean *bool);
8281 # DO NOT MATCH:
8282 # void setTabEnabled(int index, bool);
8283 $CppMode{$Version} = 1;
8284 $Detected = "$1$2$3" if(not defined $Detected);
8285 }
8286 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8287 { # MATCH:
8288 # int foo(int* this);
8289 # int bar(int this);
8290 # int baz(int throw);
8291 # DO NOT MATCH:
8292 # foo(X, this);
8293 $CppMode{$Version} = 1;
8294 $Detected = "$1$2$3$4" if(not defined $Detected);
8295 }
8296 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8297 { # MATCH:
8298 # struct template {...};
8299 # extern template foo(...);
8300 $CppMode{$Version} = 1;
8301 $Detected = "$1$2" if(not defined $Detected);
8302 }
8303
8304 if($CppMode{$Version} == 1)
8305 {
8306 if($Debug)
8307 {
8308 $Detected=~s/\A\s+//g;
8309 printMsg("INFO", "Detected code: \"$Detected\"");
8310 }
8311 }
8312
8313 # remove typedef enum NAME NAME;
8314 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8315 my $N = 0;
8316 while($N<=$#FwdTypedefs-1)
8317 {
8318 my $S = $FwdTypedefs[$N];
8319 if($S eq $FwdTypedefs[$N+1])
8320 {
8321 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008322 $CppMode{$Version} = 1;
8323
8324 if($Debug) {
8325 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8326 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008327 }
8328 $N+=2;
8329 }
8330
8331 if($CppMode{$Version}==1) {
8332 printMsg("INFO", "Using C++ compatibility mode");
8333 }
8334 }
8335
8336 if($CppMode{$Version}==1
8337 or $MinGWMode{$Version}==1)
8338 {
8339 my $IPath = $TMP_DIR."/dump$Version.i";
8340 writeFile($IPath, $Content);
8341 return $IPath;
8342 }
8343
8344 return undef;
8345}
8346
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008347sub getDump()
8348{
8349 if(not $GCC_PATH) {
8350 exitStatus("Error", "internal error - GCC path is not set");
8351 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008352
8353 my @Headers = keys(%{$Registered_Headers{$Version}});
8354 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8355
8356 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8357
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008358 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008359 my $HeaderPath = $TmpHeaderPath;
8360
8361 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008362 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008363 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8364 {
8365 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008366 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008367 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008368 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008369 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8370 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008371 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008372 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008373 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008374 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8375 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8376 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008377 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008378 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008379
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008380 if($ExtraInfo)
8381 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008382 if($IncludeString) {
8383 writeFile($ExtraInfo."/include-string", $IncludeString);
8384 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008385 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8386 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008387
8388 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8389 {
8390 my $REDIR = "";
8391 foreach my $P1 (sort @Redirects) {
8392 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8393 }
8394 writeFile($ExtraInfo."/include-redirect", $REDIR);
8395 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008396 }
8397
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008398 if(not keys(%{$TargetHeaders{$Version}}))
8399 { # Target headers
8400 addTargetHeaders($Version);
8401 }
8402
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008403 # clean memory
8404 %RecursiveIncludes = ();
8405 %Header_Include_Prefix = ();
8406 %Header_Includes = ();
8407
8408 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008409 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008410 delete($Cache{"detect_header_includes"});
8411 delete($Cache{"selectSystemHeader"});
8412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008413 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008414 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8415 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008416
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008417 if($ExtraInfo)
8418 { # extra information for other tools
8419 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8420 }
8421
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008422 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008423 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008424 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008425
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008426 if($COMMON_LANGUAGE{$Version} eq "C++") {
8427 checkCTags($Pre);
8428 }
8429
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008430 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8431 { # try to correct the preprocessor output
8432 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008435 if($COMMON_LANGUAGE{$Version} eq "C++")
8436 { # add classes and namespaces to the dump
8437 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008438 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008439 or $MinGWMode{$Version}==1) {
8440 $CHdump .= " -fpreprocessed";
8441 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008442 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008443 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008444 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008445 chdir($ORIG_DIR);
8446 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8447 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008448 my $Content = readFile($ClassDump);
8449 foreach my $ClassInfo (split(/\n\n/, $Content))
8450 {
8451 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8452 {
8453 my $CName = $1;
8454 next if($CName=~/\A(__|_objc_|_opaque_)/);
8455 $TUnit_NameSpaces{$Version}{$CName} = -1;
8456 if($CName=~/\A[\w:]+\Z/)
8457 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008458 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008459 }
8460 if($CName=~/(\w[\w:]*)::/)
8461 { # namespaces
8462 my $NS = $1;
8463 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8464 $TUnit_NameSpaces{$Version}{$NS} = 1;
8465 }
8466 }
8467 }
8468 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8469 { # read v-tables (advanced approach)
8470 my ($CName, $VTable) = ($1, $2);
8471 $ClassVTable_Content{$Version}{$CName} = $VTable;
8472 }
8473 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008474 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8475 { # add user-defined namespaces
8476 $TUnit_NameSpaces{$Version}{$NS} = 1;
8477 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008478 if($Debug)
8479 { # debug mode
8480 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008481 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008482 }
8483 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008484 }
8485
8486 # add namespaces and classes
8487 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8488 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008489 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008490 }
8491 # some GCC versions don't include class methods to the TU dump by default
8492 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008493 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008494 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8495 {
8496 next if($C_Structure{$CName});
8497 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008498 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008499 if(not $Force and $GCC_44
8500 and $OSgroup eq "linux")
8501 { # optimization for linux with GCC >= 4.4
8502 # disable this code by -force option
8503 if(index($CName, "::")!=-1)
8504 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008505 next;
8506 }
8507 }
8508 else
8509 {
8510 if($CName=~/\A(.+)::[^:]+\Z/
8511 and $TUnit_Classes{$Version}{$1})
8512 { # classes inside other classes
8513 next;
8514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008515 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008516 if(defined $TUnit_Funcs{$Version}{$CName})
8517 { # the same name for a function and type
8518 next;
8519 }
8520 if(defined $TUnit_Vars{$Version}{$CName})
8521 { # the same name for a variable and type
8522 next;
8523 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008524 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8525 }
8526 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008527 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008528 }
8529 }
8530 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8531 # create TU dump
8532 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008533 if($UserLang eq "C") {
8534 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8535 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008536 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008537 or $MinGWMode{$Version}==1) {
8538 $TUdump .= " -fpreprocessed";
8539 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008540 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008541 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8542 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008543 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008544 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008545 if($?)
8546 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008547 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008548 { # try to recompile
8549 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008550 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008551 and index($Errors, "c99_")!=-1
8552 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008553 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008554 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008555
8556 if($Debug)
8557 {
8558 # printMsg("INFO", $Errors);
8559 }
8560
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008561 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008562 resetLogging($Version);
8563 $TMP_DIR = tempdir(CLEANUP=>1);
8564 return getDump();
8565 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008566 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008567 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008568 { # add auto preamble headers and try again
8569 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008570 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008571 foreach my $Num (0 .. $#Headers)
8572 {
8573 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008574 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8575 {
8576 push_U($Include_Preamble{$Version}, $Path);
8577 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008578 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008579 }
8580 resetLogging($Version);
8581 $TMP_DIR = tempdir(CLEANUP=>1);
8582 return getDump();
8583 }
8584 elsif($Cpp0xMode{$Version}!=-1
8585 and ($Errors=~/\Q-std=c++0x\E/
8586 or $Errors=~/is not a class or namespace/))
8587 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008588 if(check_gcc($GCC_PATH, "4.6"))
8589 {
8590 $Cpp0xMode{$Version}=-1;
8591 printMsg("INFO", "Enabling c++0x mode");
8592 resetLogging($Version);
8593 $TMP_DIR = tempdir(CLEANUP=>1);
8594 $CompilerOptions{$Version} .= " -std=c++0x";
8595 return getDump();
8596 }
8597 else {
8598 printMsg("WARNING", "Probably c++0x construction detected");
8599 }
8600
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008601 }
8602 elsif($MinGWMode{$Version}==1)
8603 { # disable MinGW mode and try again
8604 $MinGWMode{$Version}=-1;
8605 resetLogging($Version);
8606 $TMP_DIR = tempdir(CLEANUP=>1);
8607 return getDump();
8608 }
8609 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008610 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008611 else {
8612 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008614 printMsg("ERROR", "some errors occurred when compiling headers");
8615 printErrorLog($Version);
8616 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008617 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008618 }
8619 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008620 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008621 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008622
8623 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8624 return $TUs[0];
8625 }
8626 else
8627 {
8628 my $Msg = "can't compile header(s)";
8629 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8630 $Msg .= "\nDid you install G++?";
8631 }
8632 exitStatus("Cannot_Compile", $Msg);
8633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008634}
8635
8636sub cmd_file($)
8637{
8638 my $Path = $_[0];
8639 return "" if(not $Path or not -e $Path);
8640 if(my $CmdPath = get_CmdPath("file")) {
8641 return `$CmdPath -b \"$Path\"`;
8642 }
8643 return "";
8644}
8645
8646sub getIncString($$)
8647{
8648 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008649 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008650 my $String = "";
8651 foreach (@{$ArrRef}) {
8652 $String .= " ".inc_opt($_, $Style);
8653 }
8654 return $String;
8655}
8656
8657sub getIncPaths(@)
8658{
8659 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008660 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 if($INC_PATH_AUTODETECT{$Version})
8662 { # auto-detecting dependencies
8663 my %Includes = ();
8664 foreach my $HPath (@HeaderPaths)
8665 {
8666 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8667 {
8668 if($Skip_Include_Paths{$Version}{$Dir}) {
8669 next;
8670 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008671 if($SystemRoot)
8672 {
8673 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8674 next;
8675 }
8676 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008677 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008678 }
8679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008680 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008681 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008682 }
8683 }
8684 else
8685 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008686 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 }
8688 return \@IncPaths;
8689}
8690
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008691sub push_U($@)
8692{ # push unique
8693 if(my $Array = shift @_)
8694 {
8695 if(@_)
8696 {
8697 my %Exist = map {$_=>1} @{$Array};
8698 foreach my $Elem (@_)
8699 {
8700 if(not defined $Exist{$Elem})
8701 {
8702 push(@{$Array}, $Elem);
8703 $Exist{$Elem} = 1;
8704 }
8705 }
8706 }
8707 }
8708}
8709
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710sub callPreprocessor($$$)
8711{
8712 my ($Path, $Inc, $LibVersion) = @_;
8713 return "" if(not $Path or not -f $Path);
8714 my $IncludeString=$Inc;
8715 if(not $Inc) {
8716 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8717 }
8718 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008719 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008720 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008721 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008722}
8723
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008724sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008725{ # native "find" is much faster than File::Find (~6x)
8726 # also the File::Find doesn't support --maxdepth N option
8727 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008728 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008729 return () if(not $Path or not -e $Path);
8730 if($OSgroup eq "windows")
8731 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008732 $Path = get_abs_path($Path);
8733 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008734 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735 if($MaxDepth!=1) {
8736 $Cmd .= " /S";
8737 }
8738 if($Type eq "d") {
8739 $Cmd .= " /AD";
8740 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008741 elsif($Type eq "f") {
8742 $Cmd .= " /A-D";
8743 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008744 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008745 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008746 {
8747 if(not $UseRegex)
8748 { # FIXME: how to search file names in MS shell?
8749 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008750 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008751 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008752 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008753 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008754 }
8755 my @AbsPaths = ();
8756 foreach my $File (@Files)
8757 {
8758 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008759 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008760 }
8761 if($Type eq "f" and not -f $File)
8762 { # skip dirs
8763 next;
8764 }
8765 push(@AbsPaths, path_format($File, $OSgroup));
8766 }
8767 if($Type eq "d") {
8768 push(@AbsPaths, $Path);
8769 }
8770 return @AbsPaths;
8771 }
8772 else
8773 {
8774 my $FindCmd = get_CmdPath("find");
8775 if(not $FindCmd) {
8776 exitStatus("Not_Found", "can't find a \"find\" command");
8777 }
8778 $Path = get_abs_path($Path);
8779 if(-d $Path and -l $Path
8780 and $Path!~/\/\Z/)
8781 { # for directories that are symlinks
8782 $Path.="/";
8783 }
8784 my $Cmd = $FindCmd." \"$Path\"";
8785 if($MaxDepth) {
8786 $Cmd .= " -maxdepth $MaxDepth";
8787 }
8788 if($Type) {
8789 $Cmd .= " -type $Type";
8790 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008791 if($Name and not $UseRegex)
8792 { # wildcards
8793 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008795 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008796 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008797 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8798 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008799 my @Files = split(/\n/, $Res);
8800 if($Name and $UseRegex)
8801 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008802 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008803 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008804 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008805 }
8806}
8807
8808sub unpackDump($)
8809{
8810 my $Path = $_[0];
8811 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 $Path = get_abs_path($Path);
8814 $Path = path_format($Path, $OSgroup);
8815 my ($Dir, $FileName) = separate_path($Path);
8816 my $UnpackDir = $TMP_DIR."/unpack";
8817 rmtree($UnpackDir);
8818 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008819
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008820 if($FileName=~s/\Q.zip\E\Z//g)
8821 { # *.zip
8822 my $UnzipCmd = get_CmdPath("unzip");
8823 if(not $UnzipCmd) {
8824 exitStatus("Not_Found", "can't find \"unzip\" command");
8825 }
8826 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008827 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008828 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008829 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008830 }
8831 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008832 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833 if(not @Contents) {
8834 exitStatus("Error", "can't extract \'$Path\'");
8835 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008836 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008837 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008838 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008839 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008840 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008841 if($OSgroup eq "windows")
8842 { # -xvzf option is not implemented in tar.exe (2003)
8843 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8844 my $TarCmd = get_CmdPath("tar");
8845 if(not $TarCmd) {
8846 exitStatus("Not_Found", "can't find \"tar\" command");
8847 }
8848 my $GzipCmd = get_CmdPath("gzip");
8849 if(not $GzipCmd) {
8850 exitStatus("Not_Found", "can't find \"gzip\" command");
8851 }
8852 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008853 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008854 if($?) {
8855 exitStatus("Error", "can't extract \'$Path\'");
8856 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008857 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008858 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008859 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860 }
8861 chdir($ORIG_DIR);
8862 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008863 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864 if(not @Contents) {
8865 exitStatus("Error", "can't extract \'$Path\'");
8866 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008867 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008868 }
8869 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008870 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008871 my $TarCmd = get_CmdPath("tar");
8872 if(not $TarCmd) {
8873 exitStatus("Not_Found", "can't find \"tar\" command");
8874 }
8875 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008876 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008877 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008878 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 }
8880 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008881 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 if(not @Contents) {
8883 exitStatus("Error", "can't extract \'$Path\'");
8884 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008885 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 }
8887 }
8888}
8889
8890sub createArchive($$)
8891{
8892 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008893 if(not $To) {
8894 $To = ".";
8895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 if(not $Path or not -e $Path
8897 or not -d $To) {
8898 return "";
8899 }
8900 my ($From, $Name) = separate_path($Path);
8901 if($OSgroup eq "windows")
8902 { # *.zip
8903 my $ZipCmd = get_CmdPath("zip");
8904 if(not $ZipCmd) {
8905 exitStatus("Not_Found", "can't find \"zip\"");
8906 }
8907 my $Pkg = $To."/".$Name.".zip";
8908 unlink($Pkg);
8909 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008910 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008911 if($?)
8912 { # cannot allocate memory (or other problems with "zip")
8913 unlink($Path);
8914 exitStatus("Error", "can't pack the ABI dump: ".$!);
8915 }
8916 chdir($ORIG_DIR);
8917 unlink($Path);
8918 return $Pkg;
8919 }
8920 else
8921 { # *.tar.gz
8922 my $TarCmd = get_CmdPath("tar");
8923 if(not $TarCmd) {
8924 exitStatus("Not_Found", "can't find \"tar\"");
8925 }
8926 my $GzipCmd = get_CmdPath("gzip");
8927 if(not $GzipCmd) {
8928 exitStatus("Not_Found", "can't find \"gzip\"");
8929 }
8930 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8931 unlink($Pkg);
8932 chdir($From);
8933 system($TarCmd, "-czf", $Pkg, $Name);
8934 if($?)
8935 { # cannot allocate memory (or other problems with "tar")
8936 unlink($Path);
8937 exitStatus("Error", "can't pack the ABI dump: ".$!);
8938 }
8939 chdir($ORIG_DIR);
8940 unlink($Path);
8941 return $To."/".$Name.".tar.gz";
8942 }
8943}
8944
8945sub is_header_file($)
8946{
8947 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8948 return $_[0];
8949 }
8950 return 0;
8951}
8952
8953sub is_not_header($)
8954{
8955 if($_[0]=~/\.\w+\Z/
8956 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8957 return 1;
8958 }
8959 return 0;
8960}
8961
8962sub is_header($$$)
8963{
8964 my ($Header, $UserDefined, $LibVersion) = @_;
8965 return 0 if(-d $Header);
8966 if(-f $Header) {
8967 $Header = get_abs_path($Header);
8968 }
8969 else
8970 {
8971 if(is_abs($Header))
8972 { # incorrect absolute path
8973 return 0;
8974 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008975 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008976 $Header = $HPath;
8977 }
8978 else
8979 { # can't find header
8980 return 0;
8981 }
8982 }
8983 if($Header=~/\.\w+\Z/)
8984 { # have an extension
8985 return is_header_file($Header);
8986 }
8987 else
8988 {
8989 if($UserDefined==2)
8990 { # specified on the command line
8991 if(cmd_file($Header)!~/HTML|XML/i) {
8992 return $Header;
8993 }
8994 }
8995 elsif($UserDefined)
8996 { # specified in the XML-descriptor
8997 # header file without an extension
8998 return $Header;
8999 }
9000 else
9001 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009002 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009003 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009004 { # !~/HTML|XML|shared|dynamic/i
9005 return $Header;
9006 }
9007 }
9008 }
9009 return 0;
9010}
9011
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009012sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009013{
9014 my $LibVersion = $_[0];
9015 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9016 {
9017 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009018 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009019
9020 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9021 detect_recursive_includes($RegHeader, $LibVersion);
9022 }
9023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009024 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9025 {
9026 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009027
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009028 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009029 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9030 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009031 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009032 }
9033 }
9034 }
9035}
9036
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009037sub familiarDirs($$)
9038{
9039 my ($D1, $D2) = @_;
9040 if($D1 eq $D2) {
9041 return 1;
9042 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009043
9044 my $U1 = index($D1, "/usr/");
9045 my $U2 = index($D2, "/usr/");
9046
9047 if($U1==0 and $U2!=0) {
9048 return 0;
9049 }
9050
9051 if($U2==0 and $U1!=0) {
9052 return 0;
9053 }
9054
9055 if(index($D2, $D1."/")==0) {
9056 return 1;
9057 }
9058
9059 # /usr/include/DIR
9060 # /home/user/DIR
9061
9062 my $DL = get_depth($D1);
9063
9064 my @Dirs1 = ($D1);
9065 while($DL - get_depth($D1)<=2
9066 and get_depth($D1)>=4
9067 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9068 push(@Dirs1, $D1);
9069 }
9070
9071 my @Dirs2 = ($D2);
9072 while(get_depth($D2)>=4
9073 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9074 push(@Dirs2, $D2);
9075 }
9076
9077 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009078 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009079 foreach my $P2 (@Dirs2)
9080 {
9081
9082 if($P1 eq $P2) {
9083 return 1;
9084 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009085 }
9086 }
9087 return 0;
9088}
9089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009090sub readHeaders($)
9091{
9092 $Version = $_[0];
9093 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9094 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009095 if($Debug)
9096 { # debug mode
9097 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009098 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009099 }
9100 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009101}
9102
9103sub prepareTypes($)
9104{
9105 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009107 { # support for old ABI dumps
9108 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009109 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009110 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009111 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9112 if($TName=~/\A(\w+)::(\w+)/) {
9113 my ($P1, $P2) = ($1, $2);
9114 if($P1 eq $P2) {
9115 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009116 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009117 else {
9118 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009120 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009121 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009122 }
9123 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009124 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009125 { # support for old ABI dumps
9126 # V < 2.5: array size == "number of elements"
9127 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009129 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009130 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009131 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009132 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009133 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009134 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009135 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009136 $Size *= $Base{"Size"};
9137 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009138 }
9139 else
9140 { # array[] is a pointer
9141 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009142 }
9143 }
9144 }
9145 }
9146 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009147 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148 { # support for old ABI dumps
9149 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009150 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009151 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009152 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009153 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009155 my %Type = get_Type($TypeId, $LibVersion);
9156 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9157 my %Type2 = get_Type($TypeId_2, $V2);
9158 if($Type{"Size"} ne $Type2{"Size"}) {
9159 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160 }
9161 }
9162 }
9163 }
9164}
9165
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009166sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009167{
9168 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009169
9170 if(not keys(%{$SymbolInfo{$LibVersion}}))
9171 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009172 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009173 {
9174 if($CheckHeadersOnly) {
9175 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9176 }
9177 else {
9178 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9179 }
9180 }
9181 }
9182
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009183 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009184 if(not checkDump(1, "2.10")
9185 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009186 { # different formats
9187 $Remangle = 1;
9188 }
9189 if($CheckHeadersOnly)
9190 { # different languages
9191 if($UserLang)
9192 { # --lang=LANG for both versions
9193 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9194 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9195 {
9196 if($UserLang eq "C++")
9197 { # remangle symbols
9198 $Remangle = 1;
9199 }
9200 elsif($UserLang eq "C")
9201 { # remove mangling
9202 $Remangle = -1;
9203 }
9204 }
9205 }
9206 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009207
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009208 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009209 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009210 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009211 { # support for old ABI dumps
9212 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9213 {
9214 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9215 {
9216 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9217 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009218 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009219 if(defined $DVal and $DVal ne "")
9220 {
9221 if($TName eq "char") {
9222 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9223 }
9224 elsif($TName eq "bool") {
9225 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9226 }
9227 }
9228 }
9229 }
9230 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009231 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009232 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009233 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9234 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009235 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009236 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9237 # + support for old ABI dumps
9238 next;
9239 }
9240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009241 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009242 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009243 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009244 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009245
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009246 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009247 if(not checkDump(1, "2.12")
9248 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009249 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009250 if($ShortName eq "operator>>")
9251 {
9252 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9253 { # corrected mangling of operator>>
9254 $SRemangle = 1;
9255 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009257 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9258 {
9259 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9260 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9261 { # corrected mangling of const global data
9262 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9263 # and incorrectly mangled by old ACC versions
9264 $SRemangle = 1;
9265 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009266 }
9267 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009268 if(not $CheckHeadersOnly)
9269 { # support for old ABI dumps
9270 if(not checkDump(1, "2.17")
9271 or not checkDump(2, "2.17"))
9272 {
9273 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9274 {
9275 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9276 {
9277 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9278 {
9279 $MnglName = $ShortName;
9280 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9281 }
9282 }
9283 }
9284 }
9285 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009286 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009287 { # support for old ABI dumps: some symbols are not mangled in old dumps
9288 # mangle both sets of symbols (old and new)
9289 # NOTE: remangling all symbols by the same mangler
9290 if($MnglName=~/\A_ZN(V|)K/)
9291 { # mangling may be incorrect on old ABI dumps
9292 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009293 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009294 }
9295 if($MnglName=~/\A_ZN(K|)V/)
9296 { # mangling may be incorrect on old ABI dumps
9297 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009298 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009299 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009300 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9301 or (not $ClassID and $CheckHeadersOnly)
9302 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9303 { # support for old ABI dumps, GCC >= 4.0
9304 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009305 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009306 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009307 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009308 $MangledNames{$LibVersion}{$MnglName} = 1;
9309 }
9310 }
9311 }
9312 elsif($Remangle==-1)
9313 { # remove mangling
9314 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009315 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009317 if(not $MnglName) {
9318 next;
9319 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009320
9321 # NOTE: duplicated entries in the ABI Dump
9322 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9323 {
9324 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9325 {
9326 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9327 {
9328 next;
9329 }
9330 }
9331 }
9332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9334 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009335 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9336
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009337 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009338 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009339 { # support for old dumps
9340 # add "Volatile" attribute
9341 if($MnglName=~/_Z(K|)V/) {
9342 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9343 }
9344 }
9345 # symbol and its symlink have same signatures
9346 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009347 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009348 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009349
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009350 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9351 {
9352 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009353
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009354 if($SymVer{$LibVersion}{$Alias}) {
9355 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9356 }
9357 }
9358
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009359 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009360 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 }
9362 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9363 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9364 }
9365 if($ExtendedCheck)
9366 { # --ext option
9367 addExtension($LibVersion);
9368 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009369
9370 # clean memory
9371 delete($SymbolInfo{$LibVersion});
9372
9373 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009374 { # detect allocable classes with public exported constructors
9375 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009376 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009377 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009378 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009379 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009380 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9381 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009382 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009383 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009384 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009385 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 $AllocableClass{$LibVersion}{$ClassName} = 1;
9387 }
9388 }
9389 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009390 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009391 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009392 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009393 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009394 if($CheckHeadersOnly)
9395 {
9396 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9397 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9398 { # all symbols except non-virtual inline
9399 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9400 }
9401 }
9402 else {
9403 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 }
9405 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009406 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009407 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 }
9409 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009410 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009411 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009412 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009413 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009414 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009415 if(defined $Base{"Type"}
9416 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009417 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009418 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009419 if($Name=~/<([^<>\s]+)>/)
9420 {
9421 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9422 $ReturnedClass{$LibVersion}{$Tid} = 1;
9423 }
9424 }
9425 else {
9426 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9427 }
9428 }
9429 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009430 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009431 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009432 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009433 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009434 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009435 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009436 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009437 if($Base{"Type"}=~/Struct|Class/)
9438 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009440 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9441 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009442 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009444 }
9445 }
9446 }
9447 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009448
9449 # mapping {short name => symbols}
9450 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009452 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009453 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009454 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009455 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009456 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009458 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009460 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009461 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009462 }
9463 }
9464 }
9465 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009466
9467 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009468 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009469 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009470 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009471 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009472 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9473 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009475 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 $ClassNames{$LibVersion}{$TName} = 1;
9478 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009479 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009480 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9481 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009482 }
9483 }
9484 }
9485 }
9486 }
9487}
9488
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009489sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009491 my ($Tid, $LibVersion) = @_;
9492 if(not $Tid) {
9493 return $Tid;
9494 }
9495
9496 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9497 {
9498 if($TName_Tid{$LibVersion}{$Name}) {
9499 return $TName_Tid{$LibVersion}{$Name};
9500 }
9501 }
9502
9503 return $Tid;
9504}
9505
9506sub register_SymbolUsage($$$)
9507{
9508 my ($InfoId, $UsedType, $LibVersion) = @_;
9509
9510 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9511 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9512 {
9513 register_TypeUsage($RTid, $UsedType, $LibVersion);
9514 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9515 }
9516 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9517 {
9518 register_TypeUsage($FCid, $UsedType, $LibVersion);
9519 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9520
9521 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9522 { # register "this" pointer
9523 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9524 }
9525 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9526 { # register "this" pointer (const method)
9527 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9528 }
9529 }
9530 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9531 {
9532 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9533 {
9534 register_TypeUsage($PTid, $UsedType, $LibVersion);
9535 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9536 }
9537 }
9538 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9539 {
9540 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9541 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9542 register_TypeUsage($TTid, $UsedType, $LibVersion);
9543 }
9544 }
9545}
9546
9547sub register_TypeUsage($$$)
9548{
9549 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009550 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009551 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009552 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009553 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009554 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009555 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009556 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009557
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009558 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009559 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009560 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009561 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009562 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009563 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9564 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9565 }
9566 }
9567
9568 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9569 {
9570 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009571 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009572 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009573 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9574 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009575 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009576 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9577 {
9578 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9579 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009580 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009581 }
9582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009583 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009584 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009585 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009586 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9587 {
9588 register_TypeUsage($MTid, $UsedType, $LibVersion);
9589 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009590 }
9591 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009592 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009593 or $TInfo{"Type"} eq "MethodPtr"
9594 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009595 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009596 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009597 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009598 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009599 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009600 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009601 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9602 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009603 }
9604 }
9605 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009606 if($TInfo{"Type"} eq "FieldPtr")
9607 {
9608 if(my $RTid = $TInfo{"Return"}) {
9609 register_TypeUsage($RTid, $UsedType, $LibVersion);
9610 }
9611 if(my $CTid = $TInfo{"Class"}) {
9612 register_TypeUsage($CTid, $UsedType, $LibVersion);
9613 }
9614 }
9615 if($TInfo{"Type"} eq "MethodPtr")
9616 {
9617 if(my $CTid = $TInfo{"Class"}) {
9618 register_TypeUsage($CTid, $UsedType, $LibVersion);
9619 }
9620 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009622 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009623 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009624 $UsedType->{$TypeId} = 1;
9625 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9626 {
9627 register_TypeUsage($BTid, $UsedType, $LibVersion);
9628 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9629 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009630 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009631 else
9632 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9633 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009634 }
9635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009636}
9637
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009638sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009639{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9641
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009642 if($Level eq "Dump")
9643 {
9644 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9645 { # TODO: check if this symbol is from
9646 # base classes of other target symbols
9647 return 1;
9648 }
9649 }
9650
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009651 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9652 { # stdc++ interfaces
9653 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009654 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655
9656 my $Target = 0;
9657 if(my $Header = $SInfo->{"Header"}) {
9658 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9659 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009660 if($ExtendedCheck)
9661 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009662 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009663 $Target = 1;
9664 }
9665 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009666 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009667 {
9668 if($Target)
9669 {
9670 if($Level eq "Dump")
9671 { # dumped
9672 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009673 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009674 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009675 return 1;
9676 }
9677 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009678 else {
9679 return 1;
9680 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009681 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009682 elsif($Level eq "Source")
9683 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009684 return 1;
9685 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009686 elsif($Level eq "Binary")
9687 { # checked
9688 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9689 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9690 return 1;
9691 }
9692 }
9693 }
9694 }
9695 else
9696 { # library is available
9697 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9698 { # exported symbols
9699 return 1;
9700 }
9701 if($Level eq "Dump")
9702 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009703 if($BinaryOnly)
9704 {
9705 if($SInfo->{"Data"})
9706 {
9707 if($Target) {
9708 return 1;
9709 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009710 }
9711 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009712 else
9713 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714 if($Target) {
9715 return 1;
9716 }
9717 }
9718 }
9719 elsif($Level eq "Source")
9720 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009721 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009722 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009723 { # skip LOCAL symbols
9724 if($Target) {
9725 return 1;
9726 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009727 }
9728 }
9729 elsif($Level eq "Binary")
9730 { # checked
9731 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9732 {
9733 if($Target) {
9734 return 1;
9735 }
9736 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009737 }
9738 }
9739 return 0;
9740}
9741
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009742sub cleanDump($)
9743{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009744 my $LibVersion = $_[0];
9745 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9746 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009747 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9748 {
9749 delete($SymbolInfo{$LibVersion}{$InfoId});
9750 next;
9751 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009752 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009753 if(not $MnglName)
9754 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009755 delete($SymbolInfo{$LibVersion}{$InfoId});
9756 next;
9757 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009758 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009759 if(not $ShortName)
9760 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009761 delete($SymbolInfo{$LibVersion}{$InfoId});
9762 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009763 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009764 if($MnglName eq $ShortName)
9765 { # remove duplicate data
9766 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009767 }
9768 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9769 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9770 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009771 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9772 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9773 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009774 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009776 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009777 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009778 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9779 {
9780 delete($TypeInfo{$LibVersion}{$Tid});
9781 next;
9782 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009783 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009784 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009785 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009786 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9787 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9788 }
9789 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009790 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9791 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9792 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009793 }
9794}
9795
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009796sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009797{
9798 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009799
9800 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9801 {
9802 if(defined $TypeInfo{$LibVersion}{$Dupl})
9803 {
9804 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9805 { # duplicate
9806 return 0;
9807 }
9808 }
9809 }
9810
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009811 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9812
9813 if(isBuiltIn($THeader)) {
9814 return 0;
9815 }
9816
9817 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9818 return 0;
9819 }
9820
9821 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9822 return 0;
9823 }
9824
9825 if(selfTypedef($Tid, $LibVersion)) {
9826 return 0;
9827 }
9828
9829 if(not isTargetType($Tid, $LibVersion)) {
9830 return 0;
9831 }
9832
9833 return 0;
9834}
9835
9836sub isTargetType($$)
9837{
9838 my ($Tid, $LibVersion) = @_;
9839
9840 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9841 { # derived
9842 return 1;
9843 }
9844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009845 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009846 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009847 if(not is_target_header($THeader, $LibVersion))
9848 { # from target headers
9849 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009850 }
9851 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009852 else
9853 { # NOTE: if type is defined in source
9854 if($UsedDump{$LibVersion}{"Public"})
9855 {
9856 if(isPrivateABI($Tid, $LibVersion)) {
9857 return 0;
9858 }
9859 else {
9860 return 1;
9861 }
9862 }
9863 else {
9864 return 0;
9865 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009866 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009867
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009868 if($SkipInternalTypes)
9869 {
9870 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9871 {
9872 return 0;
9873 }
9874 }
9875
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009876 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009877}
9878
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009879sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009880{ # remove unused data types from the ABI dump
9881 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009882
9883 my %UsedType = ();
9884
9885 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009886 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009887 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009888 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009889 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009890 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009891 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009892 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009893 next;
9894 }
9895
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009896 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009897 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009898 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009899 {
9900 my %Tree = ();
9901 register_TypeUsage($Tid, \%Tree, $LibVersion);
9902
9903 my $Tmpl = 0;
9904 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9905 {
9906 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9907 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9908 {
9909 $Tmpl = 1;
9910 last;
9911 }
9912 }
9913 if(not $Tmpl)
9914 {
9915 foreach (keys(%Tree)) {
9916 $UsedType{$_} = 1;
9917 }
9918 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009919 }
9920 }
9921 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009922
9923 my %Delete = ();
9924
9925 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009926 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009927 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009928 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009929 next;
9930 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009931
9932 if($Kind eq "Extra")
9933 {
9934 my %Tree = ();
9935 register_TypeUsage($Tid, \%Tree, $LibVersion);
9936
9937 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9938 {
9939 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9940 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9941 {
9942 $Delete{$Tid} = 1;
9943 last;
9944 }
9945 }
9946 }
9947 else
9948 {
9949 # remove type
9950 delete($TypeInfo{$LibVersion}{$Tid});
9951 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009952 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009953
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009954 if($Kind eq "Extra")
9955 { # remove duplicates
9956 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9957 {
9958 if($UsedType{$Tid})
9959 { # All & Extended
9960 next;
9961 }
9962
9963 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9964
9965 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9966 delete($TypeInfo{$LibVersion}{$Tid});
9967 }
9968 }
9969 }
9970
9971 foreach my $Tid (keys(%Delete))
9972 {
9973 delete($TypeInfo{$LibVersion}{$Tid});
9974 }
9975}
9976
9977sub check_Completeness($$)
9978{
9979 my ($Info, $LibVersion) = @_;
9980
9981 # data types
9982 if(defined $Info->{"Memb"})
9983 {
9984 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9985 {
9986 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9987 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9988 }
9989 }
9990 }
9991 if(defined $Info->{"Base"})
9992 {
9993 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9994 check_TypeInfo($Bid, $LibVersion);
9995 }
9996 }
9997 if(defined $Info->{"BaseType"}) {
9998 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9999 }
10000 if(defined $Info->{"TParam"})
10001 {
10002 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10003 {
10004 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10005 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10006 next;
10007 }
10008 if($TName eq "_BoolType") {
10009 next;
10010 }
10011 if($TName=~/\Asizeof\(/) {
10012 next;
10013 }
10014 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10015 check_TypeInfo($Tid, $LibVersion);
10016 }
10017 else
10018 {
10019 if(defined $Debug) {
10020 printMsg("WARNING", "missed type $TName");
10021 }
10022 }
10023 }
10024 }
10025
10026 # symbols
10027 if(defined $Info->{"Param"})
10028 {
10029 foreach my $Pos (keys(%{$Info->{"Param"}}))
10030 {
10031 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10032 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10033 }
10034 }
10035 }
10036 if(defined $Info->{"Return"}) {
10037 check_TypeInfo($Info->{"Return"}, $LibVersion);
10038 }
10039 if(defined $Info->{"Class"}) {
10040 check_TypeInfo($Info->{"Class"}, $LibVersion);
10041 }
10042}
10043
10044sub check_TypeInfo($$)
10045{
10046 my ($Tid, $LibVersion) = @_;
10047
10048 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10049 return;
10050 }
10051 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10052
10053 if(defined $TypeInfo{$LibVersion}{$Tid})
10054 {
10055 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10056 printMsg("ERROR", "missed type name ($Tid)");
10057 }
10058 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10059 }
10060 else {
10061 printMsg("ERROR", "missed type id $Tid");
10062 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010063}
10064
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010065sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010066{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010067 my ($TypeId, $LibVersion) = @_;
10068 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010069 if($Type{"Type"} eq "Typedef")
10070 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010071 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010072 if($Base{"Type"}=~/Class|Struct/)
10073 {
10074 if($Type{"Name"} eq $Base{"Name"}) {
10075 return 1;
10076 }
10077 elsif($Type{"Name"}=~/::(\w+)\Z/)
10078 {
10079 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10080 { # QPointer<QWidget>::QPointer
10081 return 1;
10082 }
10083 }
10084 }
10085 }
10086 return 0;
10087}
10088
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010089sub addExtension($)
10090{
10091 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010092 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010093 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010094 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010095 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010096 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10097 $TName=~s/\A(struct|union|class|enum) //;
10098 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010099
10100 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10101 "Header" => "extended.h",
10102 "ShortName" => $Symbol,
10103 "MnglName" => $Symbol,
10104 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10105 );
10106
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010107 $ExtendedSymbols{$Symbol} = 1;
10108 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10109 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010110 }
10111 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010112 $ExtendedSymbols{"external_func_0"} = 1;
10113 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10114 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010115}
10116
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010117sub findMethod($$$)
10118{
10119 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010120 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010121 {
10122 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10123 return $VirtMethodInClass;
10124 }
10125 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10126 return $VirtMethodInBaseClasses;
10127 }
10128 }
10129 return "";
10130}
10131
10132sub findMethod_Class($$$)
10133{
10134 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010135 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010136 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10137 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10138 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10139 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10140 { # search for interface with the same parameters suffix (overridden)
10141 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10142 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010143 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10144 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010145 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10146 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010147 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10148 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10149 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10150 return $Candidate;
10151 }
10152 }
10153 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010154 else
10155 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10157 return $Candidate;
10158 }
10159 }
10160 }
10161 }
10162 return "";
10163}
10164
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010165sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010166{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010167 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010168 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010169 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010170 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10171 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010173 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010174 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010175 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10176 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010177 { # pure virtual D2-destructors are marked as "virt" in the dump
10178 # virtual D2-destructors are NOT marked as "virt" in the dump
10179 # both destructors are not presented in the v-table
10180 next;
10181 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010182 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010183 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010185 }
10186}
10187
10188sub registerOverriding($)
10189{
10190 my $LibVersion = $_[0];
10191 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010192 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010193 foreach my $ClassName (@Classes)
10194 {
10195 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10196 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010197 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10198 { # pure virtuals
10199 next;
10200 }
10201 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10202 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010203 {
10204 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10205 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10206 { # both overridden virtual methods
10207 # and implemented pure virtual methods
10208 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10209 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10210 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010212 }
10213 }
10214 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10215 delete($VirtualTable{$LibVersion}{$ClassName});
10216 }
10217 }
10218}
10219
10220sub setVirtFuncPositions($)
10221{
10222 my $LibVersion = $_[0];
10223 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10224 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010225 my ($Num, $Rel) = (1, 0);
10226
10227 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010228 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010229 if($UsedDump{$LibVersion}{"DWARF"}) {
10230 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10231 }
10232 else {
10233 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10234 }
10235 foreach my $VirtFunc (@Funcs)
10236 {
10237 if($UsedDump{$LibVersion}{"DWARF"}) {
10238 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10239 }
10240 else {
10241 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10242 }
10243
10244 # set relative positions
10245 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10246 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10247 { # relative position excluding added and removed virtual functions
10248 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10249 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10250 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010254 }
10255 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010256 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010257 {
10258 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010259 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010260 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010261 }
10262 }
10263}
10264
10265sub get_sub_classes($$$)
10266{
10267 my ($ClassId, $LibVersion, $Recursive) = @_;
10268 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10269 my @Subs = ();
10270 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10271 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010272 if($Recursive)
10273 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010274 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10275 push(@Subs, $SubSubId);
10276 }
10277 }
10278 push(@Subs, $SubId);
10279 }
10280 return @Subs;
10281}
10282
10283sub get_base_classes($$$)
10284{
10285 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010286 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 return () if(not defined $ClassType{"Base"});
10288 my @Bases = ();
10289 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10290 keys(%{$ClassType{"Base"}}))
10291 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010292 if($Recursive)
10293 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010294 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10295 push(@Bases, $SubBaseId);
10296 }
10297 }
10298 push(@Bases, $BaseId);
10299 }
10300 return @Bases;
10301}
10302
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010303sub getVTable_Model($$)
10304{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010305 my ($ClassId, $LibVersion) = @_;
10306 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10307 my @Elements = ();
10308 foreach my $BaseId (@Bases, $ClassId)
10309 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010310 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010311 {
10312 if(defined $VirtualTable{$LibVersion}{$BName})
10313 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010314 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10315 if($UsedDump{$LibVersion}{"DWARF"}) {
10316 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10317 }
10318 else {
10319 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10320 }
10321 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010322 push(@Elements, $VFunc);
10323 }
10324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010325 }
10326 }
10327 return @Elements;
10328}
10329
10330sub getVShift($$)
10331{
10332 my ($ClassId, $LibVersion) = @_;
10333 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10334 my $VShift = 0;
10335 foreach my $BaseId (@Bases)
10336 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010337 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010338 {
10339 if(defined $VirtualTable{$LibVersion}{$BName}) {
10340 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 }
10343 }
10344 return $VShift;
10345}
10346
10347sub getShift($$)
10348{
10349 my ($ClassId, $LibVersion) = @_;
10350 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10351 my $Shift = 0;
10352 foreach my $BaseId (@Bases)
10353 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010354 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010355 {
10356 if($Size!=1)
10357 { # not empty base class
10358 $Shift+=$Size;
10359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010360 }
10361 }
10362 return $Shift;
10363}
10364
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010365sub getVTable_Size($$)
10366{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010367 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010368 my $Size = 0;
10369 # three approaches
10370 if(not $Size)
10371 { # real size
10372 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10373 $Size = keys(%VTable);
10374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010375 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010376 if(not $Size)
10377 { # shared library symbol size
10378 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10379 $Size /= $WORD_SIZE{$LibVersion};
10380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010381 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010382 if(not $Size)
10383 { # model size
10384 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10385 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10386 }
10387 }
10388 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010389}
10390
10391sub isCopyingClass($$)
10392{
10393 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010394 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010395}
10396
10397sub isLeafClass($$)
10398{
10399 my ($ClassId, $LibVersion) = @_;
10400 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10401}
10402
10403sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010404{ # check structured type for public fields
10405 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010406}
10407
10408sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010409{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010410 my ($TypePtr, $Skip, $Start, $End) = @_;
10411 return 0 if(not $TypePtr);
10412 if($End==-1) {
10413 $End = keys(%{$TypePtr->{"Memb"}})-1;
10414 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010415 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010416 {
10417 if($Skip and $Skip->{$MemPos})
10418 { # skip removed/added fields
10419 next;
10420 }
10421 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10422 {
10423 if(isPublic($TypePtr, $MemPos)) {
10424 return ($MemPos+1);
10425 }
10426 }
10427 }
10428 return 0;
10429}
10430
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010431sub isReserved($)
10432{ # reserved fields == private
10433 my $MName = $_[0];
10434 if($MName=~/reserved|padding|f_spare/i) {
10435 return 1;
10436 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010437 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010438 return 1;
10439 }
10440 if($MName=~/(pad\d+)/i) {
10441 return 1;
10442 }
10443 return 0;
10444}
10445
10446sub isPublic($$)
10447{
10448 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 return 0 if(not $TypePtr);
10451 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10452 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010453
10454 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10455 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010456 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010457 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010459
10460 # by name in C language
10461 # TODO: add other methods to detect private members
10462 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030010463 if($MName=~/priv|abidata|parent_object|impl/i)
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010464 { # C-styled private data
10465 return 0;
10466 }
10467 if(lc($MName) eq "abi")
10468 { # ABI information/reserved field
10469 return 0;
10470 }
10471 if(isReserved($MName))
10472 { # reserved fields
10473 return 0;
10474 }
10475
10476 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477}
10478
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010479sub getVTable_Real($$)
10480{
10481 my ($ClassName, $LibVersion) = @_;
10482 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10483 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010484 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010485 if(defined $Type{"VTable"}) {
10486 return %{$Type{"VTable"}};
10487 }
10488 }
10489 return ();
10490}
10491
10492sub cmpVTables($)
10493{
10494 my $ClassName = $_[0];
10495 my $Res = cmpVTables_Real($ClassName, 1);
10496 if($Res==-1) {
10497 $Res = cmpVTables_Model($ClassName);
10498 }
10499 return $Res;
10500}
10501
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010502sub cmpVTables_Model($)
10503{
10504 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010505 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010506 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010507 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010508 return 1;
10509 }
10510 }
10511 return 0;
10512}
10513
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010514sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515{
10516 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010517 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10518 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010519 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 my %VTable_Old = getVTable_Real($ClassName, 1);
10521 my %VTable_New = getVTable_Real($ClassName, 2);
10522 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010523 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010524 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010525 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010527 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10528 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010529 if(not defined $VTable_Old{$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);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010532 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010533 my $Entry1 = $VTable_Old{$Offset};
10534 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010535 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010536 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010537 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010538 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010539
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010540 $Entry1 = simpleVEntry($Entry1);
10541 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010542
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010543 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010544 { # NOTE: problem with vtable-dumper
10545 next;
10546 }
10547
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010548 if($Entry1 ne $Entry2)
10549 { # register as changed
10550 if($Entry1=~/::([^:]+)\Z/)
10551 {
10552 my $M1 = $1;
10553 if($Entry2=~/::([^:]+)\Z/)
10554 {
10555 my $M2 = $1;
10556 if($M1 eq $M2)
10557 { # overridden
10558 next;
10559 }
10560 }
10561 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010562 if(differentDumps("G"))
10563 {
10564 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10565 {
10566 # GCC 4.6.1: -0x00000000000000010
10567 # GCC 4.7.0: -16
10568 next;
10569 }
10570 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010571 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 }
10573 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010574 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575}
10576
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010577sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010579 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010580 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10581 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010582 my $ClassId = $TName_Tid{1}{$ClassName};
10583 if(isPrivateABI($ClassId, 1)) {
10584 next;
10585 }
10586
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010587 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010588 { # already registered
10589 next;
10590 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010591 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010592 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010593 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 foreach my $Symbol (@Affected)
10595 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010596 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010598 "Target"=>$ClassName);
10599 }
10600 }
10601 }
10602}
10603
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010604sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010605{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010606 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010607 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010608 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010610 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010611
10612 if(isPrivateABI($ClassId, 1)) {
10613 next;
10614 }
10615
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010616 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010618 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010619 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010620 if($TName_Tid{1}{$ClassName}
10621 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010622 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010623 if(defined $CompleteSignature{1}{$Symbol}
10624 and $CompleteSignature{1}{$Symbol}{"Virt"})
10625 { # override some method in v.1
10626 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010627 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010628 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010629 }
10630 }
10631 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010632 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010634 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010635 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010636 if($TName_Tid{2}{$ClassName}
10637 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010638 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010639 if(defined $CompleteSignature{2}{$Symbol}
10640 and $CompleteSignature{2}{$Symbol}{"Virt"})
10641 { # override some method in v.2
10642 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010643 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010644 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010645 }
10646 }
10647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010648 if($Level eq "Binary")
10649 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010650 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010651 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10652 { # check replacements, including pure virtual methods
10653 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10654 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010655 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010656 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10657 if($AddedPos==$RemovedPos)
10658 {
10659 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10660 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10661 last; # other methods will be reported as "added" or "removed"
10662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010664 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10665 {
10666 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10667 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010668 next;
10669 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010670 my $ProblemType = "Virtual_Replacement";
10671 my @Affected = ($RemovedVFunc);
10672 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10673 { # pure methods
10674 if(not isUsedClass($ClassId, 1, $Level))
10675 { # not a parameter of some exported method
10676 next;
10677 }
10678 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010679
10680 # affected all methods (both virtual and non-virtual ones)
10681 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10682 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010683 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010684 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010685 foreach my $AffectedInt (@Affected)
10686 {
10687 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10688 { # affected exported methods only
10689 next;
10690 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010691 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10692 next;
10693 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010694 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10695 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010696 "Target"=>get_Signature($AddedVFunc, 2),
10697 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010699 }
10700 }
10701 }
10702 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010703 if(not checkDump(1, "2.0")
10704 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010705 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010706 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010707 return;
10708 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010709 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010710 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010711 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010712 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010713
10714 if(isPrivateABI($ClassId_Old, 1)) {
10715 next;
10716 }
10717
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010718 if(not isCreatable($ClassId_Old, 1))
10719 { # skip classes without public constructors (including auto-generated)
10720 # example: class has only a private exported or private inline constructor
10721 next;
10722 }
10723 if($ClassName=~/>/)
10724 { # skip affected template instances
10725 next;
10726 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010727 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010728 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010729 if(not $ClassId_New) {
10730 next;
10731 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010732 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010733 if($Class_New{"Type"}!~/Class|Struct/)
10734 { # became typedef
10735 if($Level eq "Binary") {
10736 next;
10737 }
10738 if($Level eq "Source")
10739 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010740 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010741 if($Class_New{"Type"}!~/Class|Struct/) {
10742 next;
10743 }
10744 $ClassId_New = $Class_New{"Tid"};
10745 }
10746 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010747
10748 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10749 { # incomplete info in the ABI dump
10750 next;
10751 }
10752
10753
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10755 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 +040010756
10757 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10758 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010761 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10762 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010763 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10764 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010765 my $Shift_Old = getShift($ClassId_Old, 1);
10766 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010767 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010768 my ($Added, $Removed) = (0, 0);
10769 my @StableBases_Old = ();
10770 foreach my $BaseId (@Bases_Old)
10771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010772 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010773 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010774 push(@StableBases_Old, $BaseId);
10775 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010776 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010777 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 { # removed base
10779 # excluding namespace::SomeClass to SomeClass renaming
10780 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010781 if($Level eq "Binary")
10782 { # Binary-level
10783 if($Shift_Old ne $Shift_New)
10784 { # affected fields
10785 if(havePubFields(\%Class_Old)) {
10786 $ProblemKind .= "_And_Shift";
10787 }
10788 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10789 $ProblemKind .= "_And_Size";
10790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010791 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010792 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10793 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010794 { # affected v-table
10795 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010796 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010797 }
10798 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010799 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010800 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10801 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010802 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10803 {
10804 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10805 if($ProblemKind=~/VTable/) {
10806 $VTableChanged_M{$SubName}=1;
10807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010808 }
10809 }
10810 foreach my $Interface (@Affected)
10811 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010812 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10813 next;
10814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010815 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010816 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010817 "Target"=>$BaseName,
10818 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10819 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10820 "Shift"=>abs($Shift_New-$Shift_Old) );
10821 }
10822 $Removed+=1;
10823 }
10824 }
10825 my @StableBases_New = ();
10826 foreach my $BaseId (@Bases_New)
10827 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010828 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010829 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010830 push(@StableBases_New, $BaseId);
10831 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010832 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010833 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 { # added base
10835 # excluding namespace::SomeClass to SomeClass renaming
10836 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010837 if($Level eq "Binary")
10838 { # Binary-level
10839 if($Shift_Old ne $Shift_New)
10840 { # affected fields
10841 if(havePubFields(\%Class_Old)) {
10842 $ProblemKind .= "_And_Shift";
10843 }
10844 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10845 $ProblemKind .= "_And_Size";
10846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010847 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010848 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10849 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 { # affected v-table
10851 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010852 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010853 }
10854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010855 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10857 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010858 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10859 {
10860 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10861 if($ProblemKind=~/VTable/) {
10862 $VTableChanged_M{$SubName}=1;
10863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010864 }
10865 }
10866 foreach my $Interface (@Affected)
10867 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010868 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10869 next;
10870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010871 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010872 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010873 "Target"=>$BaseName,
10874 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10875 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10876 "Shift"=>abs($Shift_New-$Shift_Old) );
10877 }
10878 $Added+=1;
10879 }
10880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 if($Level eq "Binary")
10882 { # Binary-level
10883 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010884 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10885 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010886 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010887 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010888 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010889 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010890 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010891 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10892 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010893 if($NewPos!=$OldPos)
10894 { # changed position of the base class
10895 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010896 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010897 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10898 next;
10899 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010900 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10901 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010902 "Target"=>$BaseName,
10903 "Old_Value"=>$OldPos-1,
10904 "New_Value"=>$NewPos-1 );
10905 }
10906 }
10907 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10908 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10909 { # became non-virtual base
10910 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10911 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010912 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10913 next;
10914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010915 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10916 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010917 "Target"=>$BaseName );
10918 }
10919 }
10920 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10921 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10922 { # became virtual base
10923 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10924 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010925 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10926 next;
10927 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10929 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 "Target"=>$BaseName );
10931 }
10932 }
10933 }
10934 }
10935 # detect size changes in base classes
10936 if($Shift_Old!=$Shift_New)
10937 { # size of allocable class
10938 foreach my $BaseId (@StableBases_Old)
10939 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010940 my %BaseType = get_Type($BaseId, 1);
10941 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010942 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010943 if($Size_Old ne $Size_New
10944 and $Size_Old and $Size_New)
10945 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010946 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010947 if(isCopyingClass($BaseId, 1)) {
10948 $ProblemType = "Size_Of_Copying_Class";
10949 }
10950 elsif($AllocableClass{1}{$BaseType{"Name"}})
10951 {
10952 if($Size_New>$Size_Old)
10953 { # increased size
10954 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010956 else
10957 { # decreased size
10958 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10959 if(not havePubFields(\%Class_Old))
10960 { # affected class has no public members
10961 next;
10962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010963 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010964 }
10965 next if(not $ProblemType);
10966 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10967 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010968 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10969 next;
10970 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010971 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10972 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010973 "Target"=>$BaseType{"Name"},
10974 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10975 "New_Size"=>$Size_New*$BYTE_SIZE );
10976 }
10977 }
10978 }
10979 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010980 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010981 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010982 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 { # compare virtual tables size in base classes
10984 my $VShift_Old = getVShift($ClassId_Old, 1);
10985 my $VShift_New = getVShift($ClassId_New, 2);
10986 if($VShift_Old ne $VShift_New)
10987 { # changes in the base class or changes in the list of base classes
10988 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10989 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10990 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010991 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010992 foreach my $BaseId (@AllBases_Old)
10993 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010994 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010995 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 { # lost base
10997 next;
10998 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010999 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11000 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011001 if($VSize_Old!=$VSize_New)
11002 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011003 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011004 { # TODO: affected non-virtual methods?
11005 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011006 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11007 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011009 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011010 { # skip interfaces that have not changed the absolute virtual position
11011 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011012 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011013 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11014 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011016 $VTableChanged_M{$BaseType{"Name"}} = 1;
11017 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011018 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11019 { # the reason of the layout change: added virtual functions
11020 next if($VirtualReplacement{$VirtFunc});
11021 my $ProblemType = "Added_Virtual_Method";
11022 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11023 $ProblemType = "Added_Pure_Virtual_Method";
11024 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011025 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011026 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011027 "Target"=>get_Signature($VirtFunc, 2) );
11028 }
11029 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11030 { # the reason of the layout change: removed virtual functions
11031 next if($VirtualReplacement{$VirtFunc});
11032 my $ProblemType = "Removed_Virtual_Method";
11033 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11034 $ProblemType = "Removed_Pure_Virtual_Method";
11035 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011036 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011037 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011038 "Target"=>get_Signature($VirtFunc, 1) );
11039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040 }
11041 }
11042 }
11043 }
11044 }
11045 }
11046 }
11047}
11048
11049sub isCreatable($$)
11050{
11051 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011052 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011053 or isCopyingClass($ClassId, $LibVersion)) {
11054 return 1;
11055 }
11056 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11057 { # Fix for incomplete data: if this class has
11058 # a base class then it should also has a constructor
11059 return 1;
11060 }
11061 if($ReturnedClass{$LibVersion}{$ClassId})
11062 { # returned by some method of this class
11063 # or any other class
11064 return 1;
11065 }
11066 return 0;
11067}
11068
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011070{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011071 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11073 { # parameter of some exported method
11074 return 1;
11075 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011076 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11077 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 { # method from target class
11079 return 1;
11080 }
11081 return 0;
11082}
11083
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011084sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011085{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011087 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011088 # - virtual
11089 # - pure-virtual
11090 # - non-virtual
11091 if($CompleteSignature{1}{$Interface}{"Data"})
11092 { # global data is not affected
11093 return;
11094 }
11095 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011096 if(not $Class_Id) {
11097 return;
11098 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011099 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011100 if(cmpVTables_Real($CName, 1)==0)
11101 { # no changes
11102 return;
11103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011104 $CheckedTypes{$Level}{$CName} = 1;
11105 if($Level eq "Binary")
11106 { # Binary-level
11107 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11108 and not isUsedClass($Class_Id, 1, $Level))
11109 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011110 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011111 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011113 }
11114 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11115 {
11116 if(defined $VirtualTable{2}{$CName}{$Func}
11117 and defined $CompleteSignature{2}{$Func})
11118 {
11119 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11120 and $CompleteSignature{2}{$Func}{"PureVirt"})
11121 { # became pure virtual
11122 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11123 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011124 "Target"=>get_Signature_M($Func, 1) );
11125 $VTableChanged_M{$CName} = 1;
11126 }
11127 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11128 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11129 { # became non-pure virtual
11130 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11131 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011132 "Target"=>get_Signature_M($Func, 1) );
11133 $VTableChanged_M{$CName} = 1;
11134 }
11135 }
11136 }
11137 if($Level eq "Binary")
11138 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011139 # check virtual table structure
11140 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11141 {
11142 next if($Interface eq $AddedVFunc);
11143 next if($VirtualReplacement{$AddedVFunc});
11144 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11145 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11146 { # pure virtual methods affect all others (virtual and non-virtual)
11147 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011148 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011149 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011150 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011151 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011152 elsif(not defined $VirtualTable{1}{$CName}
11153 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011154 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011156 { # became polymorphous class, added v-table pointer
11157 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011158 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011159 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011160 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011161 }
11162 else
11163 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011164 my $VSize_Old = getVTable_Size($CName, 1);
11165 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011166 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011167 if(isCopyingClass($Class_Id, 1))
11168 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11169 my $ProblemType = "Added_Virtual_Method";
11170 if(isLeafClass($Class_Id, 1)) {
11171 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11172 }
11173 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11174 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011175 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011176 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011177 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011178 else
11179 {
11180 my $ProblemType = "Added_Virtual_Method";
11181 if(isLeafClass($Class_Id, 1)) {
11182 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11183 }
11184 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11185 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011186 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011187 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011189 }
11190 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011191 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11192 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011193 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011194 if(defined $VirtualTable{1}{$CName}
11195 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011196 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011197 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11198 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011199
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011200 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011202 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11203 foreach my $ASymbol (@Affected)
11204 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011205 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11206 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011207 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011208 next;
11209 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011210 }
11211 $CheckedSymbols{$Level}{$ASymbol} = 1;
11212 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11213 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011214 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011215 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 }
11219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011220 else {
11221 # safe
11222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011223 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011224 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11225 {
11226 next if($VirtualReplacement{$RemovedVFunc});
11227 if($RemovedVFunc eq $Interface
11228 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11229 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011230 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011231 next;
11232 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011233 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 { # became non-polymorphous class, removed v-table pointer
11235 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11236 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011238 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011239 }
11240 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11241 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11242 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011243 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011244 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011245 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11246 next;
11247 }
11248 my $VPos_New = -1;
11249 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011251 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11252 }
11253 else
11254 {
11255 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011256 next;
11257 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011258 }
11259 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11260 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11261 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11262 {
11263 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11264 foreach my $ASymbol (@Affected)
11265 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011266 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11267 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011268 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011269 next;
11270 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011271 }
11272 my $ProblemType = "Removed_Virtual_Method";
11273 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11274 $ProblemType = "Removed_Pure_Virtual_Method";
11275 }
11276 $CheckedSymbols{$Level}{$ASymbol} = 1;
11277 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11278 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011279 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011280 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011282 }
11283 }
11284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011285 }
11286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011287 else
11288 { # Source-level
11289 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011290 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011291 next if($Interface eq $AddedVFunc);
11292 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011294 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11295 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011296 "Target"=>get_Signature($AddedVFunc, 2) );
11297 }
11298 }
11299 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11300 {
11301 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11302 {
11303 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11304 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011305 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011306 }
11307 }
11308 }
11309}
11310
11311sub find_MemberPair_Pos_byName($$)
11312{
11313 my ($Member_Name, $Pair_Type) = @_;
11314 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11315 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11316 {
11317 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11318 {
11319 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11320 $Name=~s/\A[_]+|[_]+\Z//g;
11321 if($Name eq $Member_Name) {
11322 return $MemberPair_Pos;
11323 }
11324 }
11325 }
11326 return "lost";
11327}
11328
11329sub find_MemberPair_Pos_byVal($$)
11330{
11331 my ($Member_Value, $Pair_Type) = @_;
11332 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11333 {
11334 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11335 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11336 return $MemberPair_Pos;
11337 }
11338 }
11339 return "lost";
11340}
11341
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011342sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011343{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011344 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011345 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011346 if( $_->{"T1"} eq $_[0]
11347 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011348 {
11349 return 1;
11350 }
11351 }
11352 return 0;
11353}
11354
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011355sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011356{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011357 my %IDs = (
11358 "T1" => $_[0],
11359 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011360 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011361 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011362}
11363
11364sub isRenamed($$$$$)
11365{
11366 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11367 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11368 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011369 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011370 if(not defined $Type2->{"Memb"}{$MemPos}) {
11371 return "";
11372 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011373 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011374 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011375
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011376 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11377 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011378 if($MemberPair_Pos_Rev eq "lost")
11379 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011380 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11381 { # base type match
11382 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011384 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11385 { # exact type match
11386 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011388 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11389 { # size match
11390 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011391 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011392 if(isReserved($Pair_Name))
11393 { # reserved fields
11394 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011395 }
11396 }
11397 return "";
11398}
11399
11400sub isLastElem($$)
11401{
11402 my ($Pos, $TypeRef) = @_;
11403 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011404 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011405 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11406 return 1;
11407 }
11408 elsif($Name=~/END|NLIMITS\Z/)
11409 { # __RLIMIT_NLIMITS
11410 return 1;
11411 }
11412 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11413 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11414 { # NImageFormats, NColorRoles
11415 return 1;
11416 }
11417 return 0;
11418}
11419
11420sub nonComparable($$)
11421{
11422 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011423
11424 my $N1 = $T1->{"Name"};
11425 my $N2 = $T2->{"Name"};
11426
11427 $N1=~s/\A(struct|union|enum) //;
11428 $N2=~s/\A(struct|union|enum) //;
11429
11430 if($N1 ne $N2
11431 and not isAnon($N1)
11432 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011433 { # different names
11434 if($T1->{"Type"} ne "Pointer"
11435 or $T2->{"Type"} ne "Pointer")
11436 { # compare base types
11437 return 1;
11438 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011439 if($N1!~/\Avoid\s*\*/
11440 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011441 {
11442 return 1;
11443 }
11444 }
11445 elsif($T1->{"Type"} ne $T2->{"Type"})
11446 { # different types
11447 if($T1->{"Type"} eq "Class"
11448 and $T2->{"Type"} eq "Struct")
11449 { # "class" to "struct"
11450 return 0;
11451 }
11452 elsif($T2->{"Type"} eq "Class"
11453 and $T1->{"Type"} eq "Struct")
11454 { # "struct" to "class"
11455 return 0;
11456 }
11457 else
11458 { # "class" to "enum"
11459 # "union" to "class"
11460 # ...
11461 return 1;
11462 }
11463 }
11464 return 0;
11465}
11466
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011467sub isOpaque($)
11468{
11469 my $T = $_[0];
11470 if(not defined $T->{"Memb"})
11471 {
11472 return 1;
11473 }
11474 return 0;
11475}
11476
11477sub removeVPtr($)
11478{ # support for old ABI dumps
11479 my $TPtr = $_[0];
11480 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11481 if($#Pos>=1)
11482 {
11483 foreach my $Pos (0 .. $#Pos-1)
11484 {
11485 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11486 }
11487 delete($TPtr->{"Memb"}{$#Pos});
11488 }
11489}
11490
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011491sub isPrivateABI($$)
11492{
11493 my ($TypeId, $LibVersion) = @_;
11494
11495 if($CheckPrivateABI) {
11496 return 0;
11497 }
11498
11499 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11500 return 1;
11501 }
11502
11503 return 0;
11504}
11505
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011506sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011507{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011508 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011509 return {} if(not $Type1_Id or not $Type2_Id);
11510
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011511 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011512 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011513 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011514 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011515
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011516 my %Type1 = get_Type($Type1_Id, 1);
11517 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011518 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011519 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011520 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011521
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011522 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11523 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011524
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011525 if(defined $UsedDump{1}{"DWARF"})
11526 {
11527 if($Type1_Pure{"Name"} eq "__unknown__"
11528 or $Type2_Pure{"Name"} eq "__unknown__")
11529 { # Error ABI dump
11530 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11531 }
11532 }
11533
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011534 if(isPrivateABI($Type1_Id, 1)) {
11535 return {};
11536 }
11537
11538 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11539 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11540
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011541 my %SubProblems = ();
11542
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011543 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11544 {
11545 if($Type1_Pure{"Type"}=~/Struct|Union/
11546 and $Type2_Pure{"Type"}=~/Struct|Union/)
11547 {
11548 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11549 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011550 if(not defined $UsedDump{1}{"DWARF"}
11551 and not defined $UsedDump{2}{"DWARF"})
11552 {
11553 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11554 "Target"=>$Type1_Pure{"Name"},
11555 "Type_Name"=>$Type1_Pure{"Name"} );
11556 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011557
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011558 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011559 }
11560 }
11561 }
11562
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011563 if(not $Type1_Pure{"Size"}
11564 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011565 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011566 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11567 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11568 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011569 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011570 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011571 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011572 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011574 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011575 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011576 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11577 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11578 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011579
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011580 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11581 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011582 }
11583
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011584 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11585 { # support for old ABI dumps
11586 # _vptr field added in 3.0
11587 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11588 {
11589 if(defined $Type2_Pure{"Memb"}
11590 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11591 {
11592 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11593 delete($Type2_Pure{"Memb"}{0});
11594 }
11595 else {
11596 removeVPtr(\%Type2_Pure);
11597 }
11598 }
11599 }
11600 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11601 {
11602 if(defined $Type1_Pure{"Memb"}
11603 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11604 {
11605 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11606 delete($Type1_Pure{"Memb"}{0});
11607 }
11608 else {
11609 removeVPtr(\%Type1_Pure);
11610 }
11611 }
11612 }
11613 }
11614
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011615 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11616 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011617
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011618 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011619 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11620 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011621 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011622 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11623 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011624 if($Base_1{"Name"} ne $Base_2{"Name"})
11625 {
11626 if(differentDumps("G")
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030011627 or differentDumps("V")
11628 or $SkipTypedefUncover)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011629 { # different GCC versions or different dumps
11630 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11631 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11632 # std::__va_list and __va_list
11633 $Base_1{"Name"}=~s/\A(\w+::)+//;
11634 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011635 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11636 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011638 }
11639 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11640 and $Base_1{"Name"} ne $Base_2{"Name"})
11641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011642 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011643 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011644 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 {
11646 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11647 "Target"=>$Typedef_1{"Name"},
11648 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011649 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11650 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11651 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011652 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11653 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011654
11655 if(defined $UsedDump{1}{"DWARF"})
11656 {
11657 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11658 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11659 { # Error ABI dump
11660 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11661 }
11662 }
11663
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011664 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011665 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011666 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11667 {
11668 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11669 "Target"=>$Typedef_1{"Name"},
11670 "Type_Name"=>$Typedef_1{"Name"},
11671 "Old_Value"=>$Base_1{"Name"},
11672 "New_Value"=>$Base_2{"Name"} );
11673 }
11674 else
11675 {
11676 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11677 "Target"=>$Typedef_1{"Name"},
11678 "Type_Name"=>$Typedef_1{"Name"},
11679 "Old_Value"=>$Base_1{"Name"},
11680 "New_Value"=>$Base_2{"Name"} );
11681 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011683 }
11684 }
11685 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11686 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011687 my $TT1 = $Type1_Pure{"Type"};
11688 my $TT2 = $Type2_Pure{"Type"};
11689
11690 if($TT1 ne $TT2
11691 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011692 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011693 my $Short1 = $Type1_Pure{"Name"};
11694 my $Short2 = $Type2_Pure{"Name"};
11695
11696 $Short1=~s/\A\Q$TT1\E //ig;
11697 $Short2=~s/\A\Q$TT2\E //ig;
11698
11699 if($Short1 eq $Short2)
11700 {
11701 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11702 "Target"=>$Type1_Pure{"Name"},
11703 "Type_Name"=>$Type1_Pure{"Name"},
11704 "Old_Value"=>lc($Type1_Pure{"Type"}),
11705 "New_Value"=>lc($Type2_Pure{"Type"}) );
11706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011707 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011708 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011709 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011710
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011711 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011712
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011713 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11714 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11715 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11716 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011717 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011718 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011719 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011720 {
11721 my $ProblemKind = "DataType_Size";
11722 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011723 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011724 {
11725 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11726 $ProblemKind = "Size_Of_Copying_Class";
11727 }
11728 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11729 {
11730 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11731 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11732 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011733 else
11734 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011735 # descreased size of allocable class
11736 # it has no special effects
11737 }
11738 }
11739 }
11740 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11741 "Target"=>$Type1_Pure{"Name"},
11742 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011743 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011744 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011745 }
11746 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011747 if(defined $Type1_Pure{"BaseType"}
11748 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011749 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011750 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11751 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011752 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011753 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11754 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011755 }
11756 }
11757 }
11758 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11759 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11760 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11761 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11762 { # detect removed and renamed fields
11763 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11764 next if(not $Member_Name);
11765 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);
11766 if($MemberPair_Pos eq "lost")
11767 {
11768 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11769 {
11770 if(isUnnamed($Member_Name))
11771 { # support for old-version dumps
11772 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011773 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 next;
11775 }
11776 }
11777 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11778 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011779 $RenamedField{$Member_Pos} = $RenamedTo;
11780 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011781 }
11782 else
11783 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011784 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785 }
11786 }
11787 elsif($Type1_Pure{"Type"} eq "Enum")
11788 {
11789 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11790 next if($Member_Value1 eq "");
11791 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11792 if($MemberPair_Pos ne "lost")
11793 { # renamed
11794 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11795 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11796 if($MemberPair_Pos_Rev eq "lost")
11797 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011798 $RenamedField{$Member_Pos} = $RenamedTo;
11799 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011800 }
11801 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011802 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011803 }
11804 }
11805 else
11806 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011807 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011808 }
11809 }
11810 }
11811 else
11812 { # related
11813 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11814 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11815 }
11816 }
11817 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11818 { # detect added fields
11819 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11820 next if(not $Member_Name);
11821 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);
11822 if($MemberPair_Pos eq "lost")
11823 {
11824 if(isUnnamed($Member_Name))
11825 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011826 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011827 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011828 next;
11829 }
11830 }
11831 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11832 {
11833 if(not $RenamedField_Rev{$Member_Pos})
11834 { # added
11835 $AddedField{$Member_Pos}=1;
11836 }
11837 }
11838 }
11839 }
11840 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11841 { # detect moved fields
11842 my (%RelPos, %RelPosName, %AbsPos) = ();
11843 my $Pos = 0;
11844 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11845 { # relative positions in 1st version
11846 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11847 next if(not $Member_Name);
11848 if(not $RemovedField{$Member_Pos})
11849 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011850 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 $RelPosName{1}{$Pos} = $Member_Name;
11852 $AbsPos{1}{$Pos++} = $Member_Pos;
11853 }
11854 }
11855 $Pos = 0;
11856 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11857 { # relative positions in 2nd version
11858 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11859 next if(not $Member_Name);
11860 if(not $AddedField{$Member_Pos})
11861 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011862 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011863 $RelPosName{2}{$Pos} = $Member_Name;
11864 $AbsPos{2}{$Pos++} = $Member_Pos;
11865 }
11866 }
11867 foreach my $Member_Name (keys(%{$RelPos{1}}))
11868 {
11869 my $RPos1 = $RelPos{1}{$Member_Name};
11870 my $AbsPos1 = $NameToPosA{$Member_Name};
11871 my $Member_Name2 = $Member_Name;
11872 if(my $RenamedTo = $RenamedField{$AbsPos1})
11873 { # renamed
11874 $Member_Name2 = $RenamedTo;
11875 }
11876 my $RPos2 = $RelPos{2}{$Member_Name2};
11877 if($RPos2 ne "" and $RPos1 ne $RPos2)
11878 { # different relative positions
11879 my $AbsPos2 = $NameToPosB{$Member_Name2};
11880 if($AbsPos1 ne $AbsPos2)
11881 { # different absolute positions
11882 my $ProblemType = "Moved_Field";
11883 if(not isPublic(\%Type1_Pure, $AbsPos1))
11884 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011885 if($Level eq "Source") {
11886 next;
11887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011888 $ProblemType = "Moved_Private_Field";
11889 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011890 if($Level eq "Binary"
11891 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011892 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011893 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011894 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011895 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011896 if($MemSize1 ne $MemSize2) {
11897 $ProblemType .= "_And_Size";
11898 }
11899 }
11900 if($ProblemType eq "Moved_Private_Field") {
11901 next;
11902 }
11903 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11904 "Target"=>$Member_Name,
11905 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011906 "Old_Value"=>$RPos1,
11907 "New_Value"=>$RPos2 );
11908 }
11909 }
11910 }
11911 }
11912 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011913 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11915 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011916 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 if(my $RenamedTo = $RenamedField{$Member_Pos})
11918 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011919 if(defined $Constants{2}{$Member_Name})
11920 {
11921 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11922 { # define OLD NEW
11923 next; # Safe
11924 }
11925 }
11926
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011927 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11928 {
11929 if(isPublic(\%Type1_Pure, $Member_Pos))
11930 {
11931 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11932 "Target"=>$Member_Name,
11933 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011934 "Old_Value"=>$Member_Name,
11935 "New_Value"=>$RenamedTo );
11936 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011937 elsif(isReserved($Member_Name))
11938 {
11939 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11940 "Target"=>$Member_Name,
11941 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011942 "Old_Value"=>$Member_Name,
11943 "New_Value"=>$RenamedTo );
11944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 }
11946 elsif($Type1_Pure{"Type"} eq "Enum")
11947 {
11948 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11949 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11950 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 "Old_Value"=>$Member_Name,
11952 "New_Value"=>$RenamedTo );
11953 }
11954 }
11955 elsif($RemovedField{$Member_Pos})
11956 { # removed
11957 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11958 {
11959 my $ProblemType = "Removed_Field";
11960 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011961 or isUnnamed($Member_Name))
11962 {
11963 if($Level eq "Source") {
11964 next;
11965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011966 $ProblemType = "Removed_Private_Field";
11967 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011968 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011969 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 {
11971 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11972 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011973 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 +040011974 { # changed offset
11975 $ProblemType .= "_And_Layout";
11976 }
11977 }
11978 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11979 { # affected size
11980 $ProblemType .= "_And_Size";
11981 }
11982 }
11983 if($ProblemType eq "Removed_Private_Field") {
11984 next;
11985 }
11986 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11987 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011988 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011989 }
11990 elsif($Type2_Pure{"Type"} eq "Union")
11991 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011992 if($Level eq "Binary"
11993 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011994 {
11995 %{$SubProblems{"Removed_Union_Field_And_Size"}{$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 else
12000 {
12001 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12002 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012003 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 }
12005 }
12006 elsif($Type1_Pure{"Type"} eq "Enum")
12007 {
12008 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12009 "Target"=>$Member_Name,
12010 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012011 "Old_Value"=>$Member_Name );
12012 }
12013 }
12014 else
12015 { # changed
12016 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12017 if($Type1_Pure{"Type"} eq "Enum")
12018 {
12019 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12020 next if($Member_Value1 eq "");
12021 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12022 next if($Member_Value2 eq "");
12023 if($Member_Value1 ne $Member_Value2)
12024 {
12025 my $ProblemType = "Enum_Member_Value";
12026 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12027 $ProblemType = "Enum_Last_Member_Value";
12028 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029 if($SkipConstants{1}{$Member_Name}) {
12030 $ProblemType = "Enum_Private_Member_Value";
12031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012032 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12033 "Target"=>$Member_Name,
12034 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012035 "Old_Value"=>$Member_Value1,
12036 "New_Value"=>$Member_Value2 );
12037 }
12038 }
12039 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12040 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012041 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12042 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12043
12044 if($Access1 ne "private"
12045 and $Access2 eq "private")
12046 {
12047 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12048 "Target"=>$Member_Name,
12049 "Type_Name"=>$Type1_Pure{"Name"});
12050 }
12051 elsif($Access1 ne "protected"
12052 and $Access1 ne "private"
12053 and $Access2 eq "protected")
12054 {
12055 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12056 "Target"=>$Member_Name,
12057 "Type_Name"=>$Type1_Pure{"Name"});
12058 }
12059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12061 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012062 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12064 $SizeV1 = $BSize1;
12065 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012066 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012067 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12068 $SizeV2 = $BSize2;
12069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012070 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12071 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012072 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012073 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012074 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012075 {
12076 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12077 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12078 { # field size change (including anon-structures and unions)
12079 # - same types
12080 # - unnamed types
12081 # - bitfields
12082 my $ProblemType = "Field_Size";
12083 if(not isPublic(\%Type1_Pure, $Member_Pos)
12084 or isUnnamed($Member_Name))
12085 { # should not be accessed by applications, goes to "Low Severity"
12086 # example: "abidata" members in GStreamer types
12087 $ProblemType = "Private_".$ProblemType;
12088 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012089 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 +040012090 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012091 if($Type2_Pure{"Type"} ne "Union"
12092 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012093 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012094 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 +040012095 { # changed offset
12096 $ProblemType .= "_And_Layout";
12097 }
12098 }
12099 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12100 $ProblemType .= "_And_Type_Size";
12101 }
12102 }
12103 if($ProblemType eq "Private_Field_Size")
12104 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012105 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012106 if($ProblemType eq "Field_Size")
12107 {
12108 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12109 { # Low severity
12110 $ProblemType = "Struct_Field_Size_Increased";
12111 }
12112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012113 if($ProblemType)
12114 { # register a problem
12115 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12116 "Target"=>$Member_Name,
12117 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012118 "Old_Size"=>$SizeV1,
12119 "New_Size"=>$SizeV2);
12120 }
12121 }
12122 }
12123 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12124 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12125 { # do NOT check bitfield type changes
12126 next;
12127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012128 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012129 {
12130 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12131 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12132 {
12133 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12134 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012135 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012136 }
12137 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12138 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12139 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012140 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012141 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012142 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012143 }
12144 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012145 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12146 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012147 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012148 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12149 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012150
12151 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012153 or $ProblemType eq "Field_Type_And_Size"
12154 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012155 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012156 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012157 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012158 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012159 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012160 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012161 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012162 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012163 }
12164 }
12165 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12166 {
12167 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012169 }
12170 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012171 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012172 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012173 }
12174 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12175 {
12176 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012177 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012178 }
12179 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012180 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012181 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012182 }
12183 }
12184 }
12185
12186 if($Level eq "Source")
12187 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012188 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012189 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012190 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12191 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012192
12193 if($ProblemType eq "Field_Type")
12194 {
12195 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012196 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 }
12198 }
12199 }
12200 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012201
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012202 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012203 {
12204 my $ProblemType_Init = $ProblemType;
12205 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012206 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 if(not isPublic(\%Type1_Pure, $Member_Pos)
12208 or isUnnamed($Member_Name)) {
12209 $ProblemType = "Private_".$ProblemType;
12210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012211 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 +040012212 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012213 if($Type2_Pure{"Type"} ne "Union"
12214 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012216 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 +040012217 { # changed offset
12218 $ProblemType .= "_And_Layout";
12219 }
12220 }
12221 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12222 $ProblemType .= "_And_Type_Size";
12223 }
12224 }
12225 }
12226 else
12227 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012228 # TODO: Private_Field_Type rule?
12229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230 if(not isPublic(\%Type1_Pure, $Member_Pos)
12231 or isUnnamed($Member_Name)) {
12232 next;
12233 }
12234 }
12235 if($ProblemType eq "Private_Field_Type_And_Size")
12236 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012237 }
12238 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12239 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012240 "Type_Name"=>$Type1_Pure{"Name"});
12241
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012242 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012243 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012244 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012245 }
12246 }
12247 if(not isPublic(\%Type1_Pure, $Member_Pos))
12248 { # do NOT check internal type changes
12249 next;
12250 }
12251 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012252 { # checking member type changes
12253 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12254
12255 my %DupProblems = ();
12256
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012257 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012259 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012261 if(not defined $AllAffected)
12262 {
12263 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12264 next;
12265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012267
12268 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12269 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12270
12271 if(not defined $AllAffected)
12272 {
12273 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012274 }
12275 }
12276 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012277
12278 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012279 }
12280 }
12281 }
12282 }
12283 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12284 { # checking added members, public and private
12285 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12286 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012287 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012288 if($AddedField{$Member_Pos})
12289 { # added
12290 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12291 {
12292 my $ProblemType = "Added_Field";
12293 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012294 or isUnnamed($Member_Name))
12295 {
12296 if($Level eq "Source") {
12297 next;
12298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299 $ProblemType = "Added_Private_Field";
12300 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012301 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012302 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 {
12304 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12305 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012306 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 +040012307 { # changed offset
12308 $ProblemType .= "_And_Layout";
12309 }
12310 }
12311 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12312 $ProblemType .= "_And_Size";
12313 }
12314 }
12315 if($ProblemType eq "Added_Private_Field")
12316 { # skip added private fields
12317 next;
12318 }
12319 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12320 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012321 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012322 }
12323 elsif($Type2_Pure{"Type"} eq "Union")
12324 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012325 if($Level eq "Binary"
12326 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012327 {
12328 %{$SubProblems{"Added_Union_Field_And_Size"}{$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 else
12333 {
12334 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12335 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012336 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337 }
12338 }
12339 elsif($Type2_Pure{"Type"} eq "Enum")
12340 {
12341 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12342 next if($Member_Value eq "");
12343 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12344 "Target"=>$Member_Name,
12345 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012346 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 }
12348 }
12349 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012350
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012351 if($Type1_Pure{"Type"} eq "FuncPtr")
12352 {
12353 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12354 {
12355 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12356 next;
12357 }
12358
12359 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12360 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12361
12362 my $PName = "p".$PPos;
12363
12364 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12365 my %DupProblems = ();
12366
12367 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12368 {
12369 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12370 {
12371 if(not defined $AllAffected)
12372 {
12373 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12374 next;
12375 }
12376 }
12377
12378 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12379 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12380
12381 if(not defined $AllAffected)
12382 {
12383 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12384 }
12385 }
12386 }
12387
12388 %DupProblems = ();
12389 }
12390 }
12391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012392 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012393 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394}
12395
12396sub isUnnamed($) {
12397 return $_[0]=~/\Aunnamed\d+\Z/;
12398}
12399
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012400sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012401{
12402 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012403 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12404 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12405 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012407 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012408 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012409 }
12410 return $TypeName;
12411}
12412
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012413sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012414{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012415 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012416 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012417 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12418 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012419 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012420 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12421 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012422 return () if(not $Type{"Type"});
12423 if($Type{"Type"} ne $Type_Type)
12424 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012425 return () if(not $Type{"BaseType"});
12426 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012427 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012428 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429 return %Type;
12430}
12431
12432my %TypeSpecAttributes = (
12433 "Const" => 1,
12434 "Volatile" => 1,
12435 "ConstVolatile" => 1,
12436 "Restrict" => 1,
12437 "Typedef" => 1
12438);
12439
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012440sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012442 my ($TypeId, $Info) = @_;
12443 if(not $TypeId or not $Info
12444 or not $Info->{$TypeId}) {
12445 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012447 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12448 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12449 }
12450 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012451 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012453 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012454 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012455 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 return %Type;
12457}
12458
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012459sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012461 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012462 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12464 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012465 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12467 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012468 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12469 my $PLevel = 0;
12470 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12471 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012472 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012473 return $PLevel if(not $Type{"BaseType"});
12474 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12475 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12476 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012477}
12478
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012480{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012481 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012482 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012483 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12484 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012485 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012486 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12487 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012488 return %Type if(not $Type{"BaseType"});
12489 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012490 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012491 return %Type;
12492}
12493
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012494sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012495{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012496 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012497 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012498 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12499 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012500 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 my $Qual = "";
12502 if($Type{"Type"} eq "Pointer") {
12503 $Qual .= "*";
12504 }
12505 elsif($Type{"Type"} eq "Ref") {
12506 $Qual .= "&";
12507 }
12508 elsif($Type{"Type"} eq "ConstVolatile") {
12509 $Qual .= "const volatile";
12510 }
12511 elsif($Type{"Type"} eq "Const"
12512 or $Type{"Type"} eq "Volatile"
12513 or $Type{"Type"} eq "Restrict") {
12514 $Qual .= lc($Type{"Type"});
12515 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012516 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 return $BQual.$Qual;
12518}
12519
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012520sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012522 my ($TypeId, $Info) = @_;
12523 if(not $TypeId or not $Info
12524 or not $Info->{$TypeId}) {
12525 return ();
12526 }
12527 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012528 return %Type if(not $Type{"BaseType"});
12529 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012530 {
12531 if($Info->{$BTid}) {
12532 return %{$Info->{$BTid}};
12533 }
12534 else { # something is going wrong
12535 return ();
12536 }
12537 }
12538 else {
12539 return %Type;
12540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541}
12542
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012543sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012544{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012545 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012546 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012547 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12548 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549}
12550
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012551sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012552{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012553 my $Symbol = $_[0];
12554 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12555}
12556
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012557sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012558 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12559}
12560
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012561sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012562{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012563 my ($SInfo, $LibVersion) = @_;
12564
12565 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012566 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012567 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012568 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012569 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012570 return 1;
12571 }
12572 }
12573 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012574 if(my $ShortName = $SInfo->{"ShortName"})
12575 {
12576 if(index($ShortName,"<")!=-1
12577 and index($ShortName,">")!=-1) {
12578 return 1;
12579 }
12580 }
12581
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012582 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012583}
12584
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012585sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012586{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012587 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012588 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 { # class specialization
12592 return 1;
12593 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012594 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595 { # method specialization
12596 return 1;
12597 }
12598 }
12599 return 0;
12600}
12601
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012602sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012604 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012605
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012606 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012607 { # non-public global data
12608 return 0;
12609 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012610
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012611 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012612 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012613 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012614 }
12615
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012616 if($Symbol=~/\A_Z/)
12617 {
12618 if($Symbol=~/[CD][3-4]E/) {
12619 return 0;
12620 }
12621 }
12622
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012623 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 { # support for old ABI dumps in --headers-only mode
12625 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12626 {
12627 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12628 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012629 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012630 if(not $PType or $PType eq "Unknown") {
12631 return 0;
12632 }
12633 }
12634 }
12635 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012636 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012637 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012638 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 if($SkipSymbols{$LibVersion}{$Symbol})
12641 { # user defined symbols to ignore
12642 return 0;
12643 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012644
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012645 if($SymbolsListPath and not $SymbolsList{$Symbol})
12646 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012647 if(not $TargetHeadersPath or not $Header
12648 or not is_target_header($Header, 1))
12649 { # -symbols-list | -headers-list
12650 return 0;
12651 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012652 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012653
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012654 if($AppPath and not $SymbolsList_App{$Symbol})
12655 { # user defined symbols (in application)
12656 return 0;
12657 }
12658
12659 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12660
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012661 if($ClassId)
12662 {
12663 if(not isTargetType($ClassId, $LibVersion)) {
12664 return 0;
12665 }
12666 }
12667
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012668 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12669 if(not $NameSpace and $ClassId)
12670 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012671 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012672 }
12673 if($NameSpace)
12674 { # user defined namespaces to ignore
12675 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12676 return 0;
12677 }
12678 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12679 { # nested namespaces
12680 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12681 return 0;
12682 }
12683 }
12684 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012685 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012686 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012687 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012688 { # --skip-headers or <skip_headers> (not <skip_including>)
12689 if($Skip==1) {
12690 return 0;
12691 }
12692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012693 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012694 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012695 { # user defined types
12696 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12697
12698 if(not $TypesList{$CName})
12699 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012700 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12701 {
12702 $CName=~s/\A\Q$NS\E\:\://g;
12703 }
12704
12705 if(not $TypesList{$CName})
12706 {
12707 my $Found = 0;
12708
12709 while($CName=~s/\:\:.+?\Z//)
12710 {
12711 if($TypesList{$CName})
12712 {
12713 $Found = 1;
12714 last;
12715 }
12716 }
12717
12718 if(not $Found) {
12719 return 0;
12720 }
12721 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012722 }
12723 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012724
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012725 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12726 { # non-target symbols
12727 return 0;
12728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012729 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012730 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012731 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12732 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012733 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012734 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12735 { # inline virtual methods
12736 if($Type=~/InlineVirt/) {
12737 return 1;
12738 }
12739 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12740 if(not $Allocable)
12741 { # check bases
12742 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12743 {
12744 if(not isCopyingClass($DCId, $LibVersion))
12745 { # exists a derived class without default c-tor
12746 $Allocable=1;
12747 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012749 }
12750 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012751 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012752 return 0;
12753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012755 else
12756 { # inline non-virtual methods
12757 return 0;
12758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012760 }
12761 }
12762 return 1;
12763}
12764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012765sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012766{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12769 {
12770 if(link_symbol($Symbol, 1, "+Deps"))
12771 { # linker can find a new symbol
12772 # in the old-version library
12773 # So, it's not a new symbol
12774 next;
12775 }
12776 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012777 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012778 next;
12779 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012780 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012781 }
12782}
12783
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012784sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012785{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012787 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12788 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 if(link_symbol($Symbol, 2, "+Deps"))
12790 { # linker can find an old symbol
12791 # in the new-version library
12792 next;
12793 }
12794 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012795 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012796 next;
12797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012798 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012799 }
12800}
12801
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012802sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012804 my $Level = $_[0];
12805 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 { # checking added symbols
12807 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012808 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012809 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012810 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 { # checking removed symbols
12814 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012815 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012816 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012817 { # skip v-tables for templates, that should not be imported by applications
12818 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012819 if(my $CName = $VTableClass{$Symbol})
12820 {
12821 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12822 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012823 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012824 next;
12825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012826 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012827
12828 if($SkipSymbols{1}{$Symbol})
12829 { # user defined symbols to ignore
12830 next;
12831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832 }
12833 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012834 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012835 }
12836 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12837 { # symbols for pure virtual methods cannot be called by clients
12838 next;
12839 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012840 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012841 }
12842}
12843
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012844sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012846 my ($LibVersion, $V) = @_;
12847 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12848 return $Cache{"checkDump"}{$LibVersion}{$V};
12849 }
12850 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012851}
12852
12853sub detectAdded_H($)
12854{
12855 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012856 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12857 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012858 if($Level eq "Source")
12859 { # remove symbol version
12860 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12861 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012862
12863 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12864 { # skip artificial constructors
12865 next;
12866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012867 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012868 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12869 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012870 next;
12871 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012872 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012873 next;
12874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012875 if(not defined $CompleteSignature{1}{$Symbol}
12876 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12877 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012878 if($UsedDump{2}{"SrcBin"})
12879 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012880 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012881 { # support for old and different (!) ABI dumps
12882 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12883 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012884 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012885 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012886 {
12887 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12888 {
12889 if($Lang eq "C")
12890 { # support for old ABI dumps: missed extern "C" functions
12891 next;
12892 }
12893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012894 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012895 else
12896 {
12897 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012898 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012899 next;
12900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012901 }
12902 }
12903 }
12904 }
12905 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012906 }
12907 }
12908}
12909
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012911{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012913 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12914 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 if($Level eq "Source")
12916 { # remove symbol version
12917 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12918 $Symbol=$SN;
12919 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012920 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12921 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012922 next;
12923 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012924 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012925 next;
12926 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012927 if(not defined $CompleteSignature{2}{$Symbol}
12928 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012929 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012930 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012931 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012932 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012933 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012934 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12935 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012936 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012937 if($CheckHeadersOnly)
12938 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012939 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12940 {
12941 if($Lang eq "C")
12942 { # support for old ABI dumps: missed extern "C" functions
12943 next;
12944 }
12945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012947 else
12948 {
12949 if(not link_symbol($Symbol, 1, "-Deps"))
12950 { # skip removed inline symbols
12951 next;
12952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012953 }
12954 }
12955 }
12956 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012957 if(not checkDump(1, "2.15"))
12958 {
12959 if($Symbol=~/_IT_E\Z/)
12960 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12961 next;
12962 }
12963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012964 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12965 {
12966 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12967 {
12968 if(defined $Constants{2}{$Short})
12969 {
12970 my $Val = $Constants{2}{$Short}{"Value"};
12971 if(defined $Func_ShortName{2}{$Val})
12972 { # old name defined to new
12973 next;
12974 }
12975 }
12976 }
12977
12978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 $RemovedInt{$Level}{$Symbol} = 1;
12980 if($Level eq "Source")
12981 { # search for a source-compatible equivalent
12982 setAlternative($Symbol, $Level);
12983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012984 }
12985 }
12986}
12987
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012988sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012989{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012990 my $Level = $_[0];
12991 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012992 { # checking added symbols
12993 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012994 next if($CompleteSignature{2}{$Symbol}{"Private"});
12995 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012996 if($Level eq "Binary")
12997 {
12998 if($CompleteSignature{2}{$Symbol}{"InLine"})
12999 {
13000 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13001 { # skip inline non-virtual functions
13002 next;
13003 }
13004 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013005 }
13006 else
13007 { # Source
13008 if($SourceAlternative_B{$Symbol}) {
13009 next;
13010 }
13011 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013012 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013015 { # checking removed symbols
13016 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013017 next if($CompleteSignature{1}{$Symbol}{"Private"});
13018 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013019 if($Level eq "Binary")
13020 {
13021 if($CompleteSignature{1}{$Symbol}{"InLine"})
13022 {
13023 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13024 { # skip inline non-virtual functions
13025 next;
13026 }
13027 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013028 }
13029 else
13030 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013031 if(my $Alt = $SourceAlternative{$Symbol})
13032 {
13033 if(defined $CompleteSignature{1}{$Alt}
13034 and $CompleteSignature{1}{$Symbol}{"Const"})
13035 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013036 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013037 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013038 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013039 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013040 }
13041 else
13042 { # do NOT show removed symbol
13043 next;
13044 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013045 }
13046 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013047 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013048 }
13049}
13050
13051sub addParamNames($)
13052{
13053 my $LibraryVersion = $_[0];
13054 return if(not keys(%AddIntParams));
13055 my $SecondVersion = $LibraryVersion==1?2:1;
13056 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13057 {
13058 next if(not keys(%{$AddIntParams{$Interface}}));
13059 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013060 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013061 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13062 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013063 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013064 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13065 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13066 {
13067 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13068 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13069 }
13070 }
13071 else {
13072 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13073 }
13074 }
13075 }
13076 }
13077}
13078
13079sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013080{ # detect changed typedefs to show
13081 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013082 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13083 {
13084 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013085 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13086 if(not $BName1 or isAnon($BName1)) {
13087 next;
13088 }
13089 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13090 if(not $BName2 or isAnon($BName2)) {
13091 next;
13092 }
13093 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013094 $ChangedTypedef{$Typedef} = 1;
13095 }
13096 }
13097}
13098
13099sub get_symbol_suffix($$)
13100{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013101 my ($Symbol, $Full) = @_;
13102 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013103 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013105 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013106 if(not $Full) {
13107 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13108 }
13109 return $Suffix;
13110}
13111
13112sub get_symbol_prefix($$)
13113{
13114 my ($Symbol, $LibVersion) = @_;
13115 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13116 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13117 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013118 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013119 }
13120 return $ShortName;
13121}
13122
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013123sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013124{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013125 my $Symbol = $_[0];
13126 my $PSymbol = $Symbol;
13127 if(not defined $CompleteSignature{2}{$PSymbol}
13128 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13129 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13130 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013131 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013132 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013133 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013135 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13136 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013137 {
13138 if(defined $CompleteSignature{2}{$PSymbol}
13139 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13140 {
13141 $SourceAlternative{$Symbol} = $PSymbol;
13142 $SourceAlternative_B{$PSymbol} = $Symbol;
13143 if(not defined $CompleteSignature{1}{$PSymbol}
13144 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13145 $SourceReplacement{$Symbol} = $PSymbol;
13146 }
13147 }
13148 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013149 }
13150 else
13151 {
13152 foreach my $Sp ("KV", "VK", "K", "V")
13153 {
13154 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13155 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13156 {
13157 if(defined $CompleteSignature{2}{$PSymbol}
13158 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13159 {
13160 $SourceAlternative{$Symbol} = $PSymbol;
13161 $SourceAlternative_B{$PSymbol} = $Symbol;
13162 if(not defined $CompleteSignature{1}{$PSymbol}
13163 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13164 $SourceReplacement{$Symbol} = $PSymbol;
13165 }
13166 }
13167 }
13168 $PSymbol = $Symbol;
13169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 }
13171 }
13172 }
13173 return "";
13174}
13175
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013176sub getSymKind($$)
13177{
13178 my ($Symbol, $LibVersion) = @_;
13179 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13180 {
13181 return "Global_Data";
13182 }
13183 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13184 {
13185 return "Method";
13186 }
13187 return "Function";
13188}
13189
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013190sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013191{
13192 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013193 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013194
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013195 mergeBases($Level);
13196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013197 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013198 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013199 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 next;
13202 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013203 if(defined $CompleteSignature{1}{$Symbol}
13204 and $CompleteSignature{1}{$Symbol}{"Header"})
13205 { # double-check added symbol
13206 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013208 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013209 next;
13210 }
13211 if($Symbol=~/\A(_Z|\?)/)
13212 { # C++
13213 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13214 }
13215 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13216 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013217 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13218 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013219 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013220 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013221 {
13222 if($TName_Tid{1}{$AffectedClass_Name})
13223 { # class should exist in previous version
13224 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13225 { # old v-table is NOT copied by old applications
13226 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13227 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013228 "Target"=>get_Signature($Symbol, 2),
13229 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013230 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013231 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013233 }
13234 }
13235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13237 { # check all removed exported symbols
13238 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 next;
13240 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013241 if(defined $CompleteSignature{2}{$Symbol}
13242 and $CompleteSignature{2}{$Symbol}{"Header"})
13243 { # double-check removed symbol
13244 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013245 }
13246 if($CompleteSignature{1}{$Symbol}{"Private"})
13247 { # skip private methods
13248 next;
13249 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013250 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013251 next;
13252 }
13253 $CheckedSymbols{$Level}{$Symbol} = 1;
13254 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13255 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013256 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13257 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013259 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13260 {
13261 if($TName_Tid{2}{$AffectedClass_Name})
13262 { # class should exist in newer version
13263 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13264 { # old v-table is NOT copied by old applications
13265 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13266 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013267 "Target"=>get_Signature($OverriddenMethod, 1),
13268 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013269 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013272 }
13273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013274 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013275 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013276 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013277 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013278 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013279 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013281 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013282 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013283 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013284 {
13285 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13286 "Target"=>$tr_name{$Symbol},
13287 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013288 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013290 else
13291 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013292 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013293 "Target"=>$tr_name{$Symbol},
13294 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013295 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013296 }
13297 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013298 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013299 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013300 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013301 {
13302 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13303 "Target"=>$tr_name{$Symbol},
13304 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013305 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013307 else
13308 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013309 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013310 "Target"=>$tr_name{$Symbol},
13311 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013312 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013313 }
13314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013315 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13316 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13317 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13318 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13319 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 {
13321 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013322 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013323 $ProblemType = "Global_Data_Symbol_Changed_Type";
13324 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013325 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13326 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013327 "Old_Type"=>$RTName1,
13328 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013330 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013331 }
13332 }
13333 }
13334 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013335 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013336 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013337 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013339 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013341 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13343 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013344 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013345 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013346 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013347 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013348 }
13349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13351 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013352 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013353 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013355 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013356 }
13357 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013358 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013359 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013360 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013365 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013366 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013368 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013370 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013375 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013377 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013379 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013381 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013382 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 { # "volatile" to non-"volatile"
13384
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013385 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013387 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013389 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013390 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013392 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013394 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013396 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013398 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013400 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13403 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013404 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013406 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013407 }
13408 }
13409 }
13410 }
13411 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013412 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13413 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013414 $CurrentSymbol = $Symbol;
13415
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13417 if($Level eq "Source")
13418 { # remove symbol version
13419 $Symbol=$SN;
13420 }
13421 else
13422 { # Binary
13423 if(not $SV)
13424 { # symbol without version
13425 if(my $VSym = $SymVer{1}{$Symbol})
13426 { # the symbol is linked with versioned symbol
13427 if($CompleteSignature{2}{$VSym}{"MnglName"})
13428 { # show report for symbol@ver only
13429 next;
13430 }
13431 elsif(not link_symbol($VSym, 2, "-Deps"))
13432 { # changed version: sym@v1 to sym@v2
13433 # do NOT show report for symbol
13434 next;
13435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013436 }
13437 }
13438 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013439 my $PSymbol = $Symbol;
13440 if($Level eq "Source"
13441 and my $S = $SourceReplacement{$Symbol})
13442 { # take a source-compatible replacement function
13443 $PSymbol = $S;
13444 }
13445 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013446 { # private symbols
13447 next;
13448 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013449 if(not defined $CompleteSignature{1}{$Symbol}
13450 or not defined $CompleteSignature{2}{$PSymbol})
13451 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 next;
13453 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013454 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13455 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13456 { # no mangled name
13457 next;
13458 }
13459 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13460 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 { # without a header
13462 next;
13463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013464
13465 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13466 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13467 { # became pure
13468 next;
13469 }
13470 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13471 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13472 { # became non-pure
13473 next;
13474 }
13475
13476 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13477 { # exported, target, inline virtual and pure virtual
13478 next;
13479 }
13480 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13481 { # exported, target, inline virtual and pure virtual
13482 next;
13483 }
13484
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013485 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013486 {
13487 if($CompleteSignature{1}{$Symbol}{"Data"}
13488 and $CompleteSignature{2}{$PSymbol}{"Data"})
13489 {
13490 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13491 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13492 if(defined $Value1)
13493 {
13494 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13495 if(defined $Value2)
13496 {
13497 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13498 if($Value1 ne $Value2)
13499 {
13500 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13501 "Old_Value"=>$Value1,
13502 "New_Value"=>$Value2,
13503 "Target"=>get_Signature($Symbol, 1) );
13504 }
13505 }
13506 }
13507 }
13508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013509
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013510 if($CompleteSignature{2}{$PSymbol}{"Private"})
13511 {
13512 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13513 "Target"=>get_Signature_M($PSymbol, 2) );
13514 }
13515 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13516 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13517 {
13518 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13519 "Target"=>get_Signature_M($PSymbol, 2) );
13520 }
13521 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13522 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13523 {
13524 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13525 "Target"=>get_Signature_M($PSymbol, 2) );
13526 }
13527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013528 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013529 mergeVirtualTables($Symbol, $Level);
13530
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 if($COMPILE_ERRORS)
13532 { # if some errors occurred at the compiling stage
13533 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013534 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013535 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013536 { # missed information about parameters in newer version
13537 next;
13538 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013539 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013540 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013541 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013542 next;
13543 }
13544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013546 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013547 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013548 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13549 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013550 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13551 "Target"=>get_Signature($Symbol, 1)
13552 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013554 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013555 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13556 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013557 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013558 "Target"=>get_Signature($Symbol, 1)
13559 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013560 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13562 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013563 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013564 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013565 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013566 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13567 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13568 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013569 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013570 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013571 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13572 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013574 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013575 my $ProblemType = "Virtual_Method_Position";
13576 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13577 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013578 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013579 if(isUsedClass($Class_Id, 1, $Level))
13580 {
13581 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013582 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013584 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13585 next;
13586 }
13587 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013588 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013589 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13590 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013591 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013592 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013593 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 }
13596 }
13597 }
13598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013599 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13600 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 { # do NOT check type changes in pure virtuals
13602 next;
13603 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013604 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013605 if($Symbol=~/\A(_Z|\?)/
13606 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013607 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013608 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013609 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013610 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013611 }
13612 }
13613 else
13614 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013615 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013617 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013618 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13619 last if($PType2_Name eq "...");
13620 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13621 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013624 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013625 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13626 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13628 $ParamPos_Prev = "lost";
13629 }
13630 }
13631 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013632 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013633 }
13634 if($ParamPos_Prev eq "lost")
13635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013636 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013637 {
13638 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 $ProblemType = "Added_Unnamed_Parameter";
13641 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013642 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013643 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013644 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013645 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013646 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 }
13648 else
13649 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013650 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013651 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013652 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013653 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13654 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013656 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013658 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013659 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013660 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013661 "Param_Type"=>$PType2_Name,
13662 "Old_Value"=>$PName_Old,
13663 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013664 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013665 }
13666 }
13667 else
13668 {
13669 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013670 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 $ProblemType = "Added_Middle_Unnamed_Parameter";
13672 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013673 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013674 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013675 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013676 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013677 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 }
13679 }
13680 }
13681 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013682 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013683 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013684 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013685 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013687 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013689 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013690 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013691 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13692 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013693 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013694 }
13695 }
13696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013697 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013698 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013699 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013700 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13701 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013702 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13703 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013705 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013707 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13708 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13710 $ParamPos_New = "lost";
13711 }
13712 }
13713 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013714 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013715 }
13716 if($ParamPos_New eq "lost")
13717 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013718 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 {
13720 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013721 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013722 $ProblemType = "Removed_Unnamed_Parameter";
13723 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013724 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013725 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013726 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013727 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013728 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013730 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013732 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013733 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013734 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013735 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013736 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013737 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013738 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013739 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013740 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013741 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013742 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013743 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013744 "Old_Value"=>$PName,
13745 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013746 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013747 }
13748 }
13749 else
13750 {
13751 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013752 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013753 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13754 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013755 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013756 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013757 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013758 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013759 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 }
13761 }
13762 }
13763 }
13764 }
13765 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013766 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13767 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013768 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013769
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013770 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013772 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13773 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013774 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013775
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013776 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013777 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013778 if($SubProblemType eq "Return_Type_And_Size") {
13779 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13780 }
13781 elsif($SubProblemType eq "Return_Type_Format") {
13782 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13783 }
13784 else {
13785 $ProblemTypes{"Global_Data_Type"} = 1;
13786 }
13787
13788 # quals
13789 if($SubProblemType eq "Return_Type"
13790 or $SubProblemType eq "Return_Type_And_Size"
13791 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013792 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013793 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13794 { # const to non-const
13795 if($RR==2) {
13796 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13797 }
13798 else {
13799 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13800 }
13801 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013803 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13804 { # non-const to const
13805 if($RA==2) {
13806 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13807 }
13808 else {
13809 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13810 }
13811 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 }
13813 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013814 }
13815 else
13816 {
13817 # quals
13818 if($SubProblemType eq "Return_Type"
13819 or $SubProblemType eq "Return_Type_And_Size"
13820 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013821 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013822 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013823 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013824 if(addedQual($Old_Value, $New_Value, "volatile"))
13825 {
13826 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13827 if($Level ne "Source"
13828 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13829 $ProblemTypes{"Return_Type"} = 1;
13830 }
13831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013832 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013833 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13834 {
13835 if($RA==2) {
13836 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13837 }
13838 else {
13839 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13840 }
13841 if($Level ne "Source"
13842 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13843 $ProblemTypes{"Return_Type"} = 1;
13844 }
13845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013846 }
13847 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013848 if($Level eq "Binary"
13849 and not $CompleteSignature{1}{$Symbol}{"Data"})
13850 {
13851 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13852 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13853 { # if one of the architectures is unknown
13854 # then set other arhitecture to unknown too
13855 ($Arch1, $Arch2) = ("unknown", "unknown");
13856 }
13857 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 {
13860 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13861 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13862 }
13863 else
13864 {
13865 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13866 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13867 }
13868
13869 if($SubProblemType eq "Return_Type_Became_Void")
13870 {
13871 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13872 { # parameters stack has been affected
13873 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013874 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013875 }
13876 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013877 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013878 }
13879 }
13880 }
13881 elsif($SubProblemType eq "Return_Type_From_Void")
13882 {
13883 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13884 { # parameters stack has been affected
13885 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013886 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013887 }
13888 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013889 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013890 }
13891 }
13892 }
13893 elsif($SubProblemType eq "Return_Type"
13894 or $SubProblemType eq "Return_Type_And_Size"
13895 or $SubProblemType eq "Return_Type_Format")
13896 {
13897 if($Conv1{"Method"} ne $Conv2{"Method"})
13898 {
13899 if($Conv1{"Method"} eq "stack")
13900 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013901 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013902 }
13903 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013904 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013905 }
13906 }
13907 else
13908 {
13909 if($Conv1{"Method"} eq "reg")
13910 {
13911 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13912 {
13913 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013914 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013915 }
13916 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013917 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013918 }
13919 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013920 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013921 }
13922 }
13923 }
13924 }
13925 }
13926 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013927
13928 if(not keys(%ProblemTypes))
13929 { # default
13930 $ProblemTypes{$SubProblemType} = 1;
13931 }
13932
13933 foreach my $ProblemType (keys(%ProblemTypes))
13934 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013935 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013937 }
13938 if($ReturnType1_Id and $ReturnType2_Id)
13939 {
13940 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013941 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13942
13943 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013944
13945 if($CompleteSignature{1}{$Symbol}{"Data"})
13946 {
13947 if($Level eq "Binary")
13948 {
13949 if(get_PLevel($ReturnType1_Id, 1)==0)
13950 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013951 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013952 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013953
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013954 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13955 {
13956 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013957 {
13958 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13959 {
13960 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13961 last;
13962 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013963 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013964 }
13965 }
13966 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013967 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013968 {
13969 if(defined $GlobalDataObject{1}{$Symbol}
13970 and defined $GlobalDataObject{2}{$Symbol})
13971 {
13972 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13973 my $New_Size = $GlobalDataObject{2}{$Symbol};
13974 if($Old_Size!=$New_Size)
13975 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013976 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013977 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013978 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013979 }
13980 }
13981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013982 }
13983 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013984
13985 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013986 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013987 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013988 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013989 my $NewLocation = "retval";
13990 if($SubLocation and $SubLocation ne "retval") {
13991 $NewLocation = "retval->".$SubLocation;
13992 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013993 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13994 }
13995 }
13996
13997 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13998 {
13999 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14000 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014001 my $NewLocation = "retval";
14002 if($SubLocation and $SubLocation ne "retval") {
14003 $NewLocation = "retval->".$SubLocation;
14004 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014005 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014006 }
14007 }
14008 }
14009
14010 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014011 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14012 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14013 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014014 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014016 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14017 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014018 if($ThisPtr1_Id and $ThisPtr2_Id)
14019 {
14020 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014021 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14022 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014023 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014024 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014025 {
14026 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014027 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014028 }
14029 }
14030 }
14031 }
14032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014033 if($Level eq "Binary") {
14034 mergeVTables($Level);
14035 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014036 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14037 $CheckedSymbols{$Level}{$Symbol} = 1;
14038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014039}
14040
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014041sub rmQuals($$)
14042{
14043 my ($Value, $Qual) = @_;
14044 if(not $Qual) {
14045 return $Value;
14046 }
14047 if($Qual eq "all")
14048 { # all quals
14049 $Qual = "const|volatile|restrict";
14050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014051 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014052 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014053 }
14054 return $Value;
14055}
14056
14057sub cmpBTypes($$$$)
14058{
14059 my ($T1, $T2, $V1, $V2) = @_;
14060 $T1 = uncover_typedefs($T1, $V1);
14061 $T2 = uncover_typedefs($T2, $V2);
14062 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14063}
14064
14065sub addedQual($$$)
14066{
14067 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014068 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014069}
14070
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014071sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014072{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014073 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014074 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014075}
14076
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014077sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014078{
14079 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14080 $Old_Value = uncover_typedefs($Old_Value, $V1);
14081 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014082
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014083 if($Old_Value eq $New_Value)
14084 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014085 return 0;
14086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014087 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014088 { # without a qual
14089 return 0;
14090 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014091 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014092 { # became non-qual
14093 return 1;
14094 }
14095 else
14096 {
14097 my @BQ1 = getQualModel($Old_Value, $Qual);
14098 my @BQ2 = getQualModel($New_Value, $Qual);
14099 foreach (0 .. $#BQ1)
14100 { # removed qual
14101 if($BQ1[$_]==1
14102 and $BQ2[$_]!=1)
14103 {
14104 return 2;
14105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014106 }
14107 }
14108 return 0;
14109}
14110
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014111sub getQualModel($$)
14112{
14113 my ($Value, $Qual) = @_;
14114 if(not $Qual) {
14115 return $Value;
14116 }
14117
14118 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014119 while($Value=~/(\w+)/)
14120 {
14121 my $W = $1;
14122
14123 if($W eq $Qual) {
14124 $Value=~s/\b$W\b/\@/g;
14125 }
14126 else {
14127 $Value=~s/\b$W\b//g;
14128 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014129 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014130
14131 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014132 $Value=~s/[^\*\&\w]+//g;
14133
14134 # modeling
14135 # int*const*const == 011
14136 # int**const == 001
14137 my @Model = ();
14138 my @Elems = split(/[\*\&]/, $Value);
14139 if(not @Elems) {
14140 return (0);
14141 }
14142 foreach (@Elems)
14143 {
14144 if($_ eq $Qual) {
14145 push(@Model, 1);
14146 }
14147 else {
14148 push(@Model, 0);
14149 }
14150 }
14151
14152 return @Model;
14153}
14154
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014155my %StringTypes = map {$_=>1} (
14156 "char*",
14157 "char const*"
14158);
14159
14160my %CharTypes = map {$_=>1} (
14161 "char",
14162 "char const"
14163);
14164
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014165sub showVal($$$)
14166{
14167 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014168 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014169 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014170 if(substr($Value, 0, 2) eq "_Z")
14171 {
14172 if(my $Unmangled = $tr_name{$Value}) {
14173 return $Unmangled;
14174 }
14175 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014176 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177 { # strings
14178 return "\"$Value\"";
14179 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014180 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014181 { # characters
14182 return "\'$Value\'";
14183 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014184 if($Value eq "")
14185 { # other
14186 return "\'\'";
14187 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014188 return $Value;
14189}
14190
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014191sub getRegs($$$)
14192{
14193 my ($LibVersion, $Symbol, $Pos) = @_;
14194
14195 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14196 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014197 my %Regs = ();
14198 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14199 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014200 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014201 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14202 }
14203 }
14204
14205 return join(", ", sort keys(%Regs));
14206 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014207 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14208 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14209 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14210 {
14211 return "unknown";
14212 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014213
14214 return undef;
14215}
14216
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014217sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014218{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014219 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014220 if(not $Symbol) {
14221 return;
14222 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014223 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14224 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14225 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14226 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014227 if(not $PType1_Id
14228 or not $PType2_Id) {
14229 return;
14230 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014231
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014232 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014233 { # do not merge "this"
14234 if($PName1 eq "this" or $PName2 eq "this") {
14235 return;
14236 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014237 }
14238
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014239 my %Type1 = get_Type($PType1_Id, 1);
14240 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014241
14242 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14243
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014244 my %BaseType1 = get_BaseType($PType1_Id, 1);
14245 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014246
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014247 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014248
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014249 if($Level eq "Binary")
14250 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014251 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014252 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14253 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14254 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14255 {
14256 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014257 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014258 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014259 }
14260 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14261 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14262 {
14263 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014264 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014265 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014268
14269 if(defined $UsedDump{1}{"DWARF"}
14270 and defined $UsedDump{2}{"DWARF"})
14271 {
14272 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14273 {
14274 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14275 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014276
14277 if($Old_Regs ne "unknown"
14278 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014279 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014280 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014281 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014282 if($Old_Regs ne $New_Regs)
14283 {
14284 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14285 "Target"=>$PName1,
14286 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14287 "Old_Value"=>$Old_Regs,
14288 "New_Value"=>$New_Regs );
14289 }
14290 }
14291 elsif($Old_Regs and not $New_Regs)
14292 {
14293 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014294 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014295 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014296 "Old_Value"=>$Old_Regs );
14297 }
14298 elsif(not $Old_Regs and $New_Regs)
14299 {
14300 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14301 "Target"=>$PName1,
14302 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014303 "New_Value"=>$New_Regs );
14304 }
14305 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014306
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014307 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14308 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14309 {
14310 if($Old_Offset ne $New_Offset)
14311 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014312 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14313 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14314
14315 $Old_Offset = $Old_Offset - $Start1;
14316 $New_Offset = $New_Offset - $Start2;
14317
14318 if($Old_Offset ne $New_Offset)
14319 {
14320 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14321 "Target"=>$PName1,
14322 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14323 "Old_Value"=>$Old_Offset,
14324 "New_Value"=>$New_Offset );
14325 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014326 }
14327 }
14328 }
14329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014330 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014331 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14332 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014333 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014334 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014335 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14336 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014337 if(not checkDump(1, "2.13")
14338 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014339 { # support for old ABI dumps
14340 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014341 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014342 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014343 and $Value_Old eq "false" and $Value_New eq "0")
14344 { # int class::method ( bool p = 0 );
14345 # old ABI dumps: "false"
14346 # new ABI dumps: "0"
14347 $Value_Old = "0";
14348 }
14349 }
14350 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014351 if(not checkDump(1, "2.18")
14352 and checkDump(2, "2.18"))
14353 { # support for old ABI dumps
14354 if(not defined $Value_Old
14355 and substr($Value_New, 0, 2) eq "_Z") {
14356 $Value_Old = $Value_New;
14357 }
14358 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014359 if(defined $Value_Old)
14360 {
14361 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14362 if(defined $Value_New)
14363 {
14364 $Value_New = showVal($Value_New, $PType2_Id, 2);
14365 if($Value_Old ne $Value_New)
14366 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014367 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014368 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014369 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014370 "Old_Value"=>$Value_Old,
14371 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014372 }
14373 }
14374 else
14375 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014376 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014377 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014378 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014379 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014380 }
14381 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014382 elsif(defined $Value_New)
14383 {
14384 $Value_New = showVal($Value_New, $PType2_Id, 2);
14385 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14386 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014387 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014388 "New_Value"=>$Value_New );
14389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014391
14392 if($ChkRnmd)
14393 {
14394 if($PName1 and $PName2 and $PName1 ne $PName2
14395 and $PType1_Id!=-1 and $PType2_Id!=-1
14396 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14397 { # except unnamed "..." value list (Id=-1)
14398 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14399 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014400 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014401 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14402 "Old_Value"=>$PName1,
14403 "New_Value"=>$PName2,
14404 "New_Signature"=>get_Signature($Symbol, 2) );
14405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014408 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014409 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 foreach my $SubProblemType (keys(%SubProblems))
14412 { # add new problems, remove false alarms
14413 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14414 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014415
14416 # quals
14417 if($SubProblemType eq "Parameter_Type"
14418 or $SubProblemType eq "Parameter_Type_And_Size"
14419 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014420 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014421 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014422 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014423 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014424 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014425 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014426 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14427 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14428 }
14429 }
14430 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14431 {
14432 if(removedQual($Old_Value, $New_Value, "volatile")) {
14433 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014434 }
14435 }
14436 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14437 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14438 { # int to "int const"
14439 delete($SubProblems{$SubProblemType});
14440 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014441 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014442 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14443 { # "int const" to int
14444 delete($SubProblems{$SubProblemType});
14445 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014446 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14447 { # "const" to non-"const"
14448 if($RR==2) {
14449 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14450 }
14451 else {
14452 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14453 }
14454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014455 }
14456 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014457
14458 if($Level eq "Source")
14459 {
14460 foreach my $SubProblemType (keys(%SubProblems))
14461 {
14462 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14463 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14464
14465 if($SubProblemType eq "Parameter_Type")
14466 {
14467 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14468 delete($SubProblems{$SubProblemType});
14469 }
14470 }
14471 }
14472 }
14473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014474 foreach my $SubProblemType (keys(%SubProblems))
14475 { # modify/register problems
14476 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14477 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014478 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14479 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014480
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014481 my $NewProblemType = $SubProblemType;
14482 if($Old_Value eq "..." and $New_Value ne "...")
14483 { # change from "..." to "int"
14484 if($ParamPos1==0)
14485 { # ISO C requires a named argument before "..."
14486 next;
14487 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014488 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 }
14490 elsif($New_Value eq "..." and $Old_Value ne "...")
14491 { # change from "int" to "..."
14492 if($ParamPos2==0)
14493 { # ISO C requires a named argument before "..."
14494 next;
14495 }
14496 $NewProblemType = "Parameter_Became_VaList";
14497 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014498 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014499 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 {
14501 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014502 if($Arch1 eq "unknown"
14503 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014504 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014505 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 ($Arch1, $Arch2) = ("unknown", "unknown");
14507 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014508 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014509 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014510 { # real
14511 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14512 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14513 }
14514 else
14515 { # model
14516 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14517 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14518 }
14519 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014521 if($Conv1{"Method"} eq "stack")
14522 {
14523 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14524 $NewProblemType = "Parameter_Type_And_Stack";
14525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014527 elsif($Conv1{"Method"} eq "reg")
14528 {
14529 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14530 $NewProblemType = "Parameter_Type_And_Register";
14531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014532 }
14533 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014534 elsif($Conv1{"Method"} ne "unknown"
14535 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014537 if($Conv1{"Method"} eq "stack") {
14538 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014540 elsif($Conv1{"Method"} eq "register") {
14541 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014542 }
14543 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014544 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14545 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014546 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014547 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014548 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014549 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014550 "New_Signature"=>get_Signature($Symbol, 2) );
14551 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014553
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014554 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014555
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014556 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014557 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14558 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014559 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014560 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014561 {
14562 my $NewProblemType = $SubProblemType;
14563 if($SubProblemType eq "DataType_Size")
14564 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014565 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014566 { # stack has been affected
14567 $NewProblemType = "DataType_Size_And_Stack";
14568 }
14569 }
14570 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014571 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014572 }
14573 }
14574}
14575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576sub find_ParamPair_Pos_byName($$$)
14577{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014578 my ($Name, $Symbol, $LibVersion) = @_;
14579 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014581 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14582 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583 {
14584 return $ParamPos;
14585 }
14586 }
14587 return "lost";
14588}
14589
14590sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14591{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014592 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014594 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 {
14596 next if($Order eq "backward" and $ParamPos>$MediumPos);
14597 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014598 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14599 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014600 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 push(@Positions, $ParamPos);
14602 }
14603 }
14604 return @Positions;
14605}
14606
14607sub getTypeIdByName($$)
14608{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014609 my ($TypeName, $LibVersion) = @_;
14610 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014611}
14612
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014613sub diffTypes($$$)
14614{
14615 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14616 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14617 }
14618 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14619 { # skip recursive declarations
14620 return 0;
14621 }
14622
14623 pushType($_[0], $_[1], \@RecurTypes_Diff);
14624 my $Diff = diffTypes_I(@_);
14625 pop(@RecurTypes_Diff);
14626
14627 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14628}
14629
14630sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014632 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014633
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014634 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14635 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014637 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14638 { # equal types
14639 return 0;
14640 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014641 if($Type1_Pure{"Name"} eq "void")
14642 { # from void* to something
14643 return 0;
14644 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030014645 if($Type2_Pure{"Name"} eq "void")
14646 { # from something to void*
14647 return 0;
14648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 if($Type1_Pure{"Name"}=~/\*/
14650 or $Type2_Pure{"Name"}=~/\*/)
14651 { # compared in detectTypeChange()
14652 return 0;
14653 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014655 my %FloatType = map {$_=>1} (
14656 "float",
14657 "double",
14658 "long double"
14659 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014660
14661 my $T1 = $Type1_Pure{"Type"};
14662 my $T2 = $Type2_Pure{"Type"};
14663
14664 if($T1 eq "Struct"
14665 and $T2 eq "Class")
14666 { # compare as data structures
14667 $T2 = "Struct";
14668 }
14669
14670 if($T1 eq "Class"
14671 and $T2 eq "Struct")
14672 { # compare as data structures
14673 $T1 = "Struct";
14674 }
14675
14676 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014677 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014678 if($T1 eq "Intrinsic"
14679 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680 { # "int" to "enum"
14681 return 0;
14682 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014683 elsif($T2 eq "Intrinsic"
14684 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014685 { # "enum" to "int"
14686 return 0;
14687 }
14688 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014689 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014690 # ...
14691 return 1;
14692 }
14693 }
14694 else
14695 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014696 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014697 {
14698 if($FloatType{$Type1_Pure{"Name"}}
14699 or $FloatType{$Type2_Pure{"Name"}})
14700 { # "float" to "double"
14701 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014702 if($Level eq "Source")
14703 { # Safe
14704 return 0;
14705 }
14706 else {
14707 return 1;
14708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014709 }
14710 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014711 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014712 {
14713 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14714 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014715 if(not @Membs1
14716 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014717 { # private
14718 return 0;
14719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014720 if($#Membs1!=$#Membs2)
14721 { # different number of elements
14722 return 1;
14723 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014724 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014725 {
14726 foreach my $Pos (@Membs1)
14727 { # compare elements by name and value
14728 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14729 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14730 { # different names
14731 return 1;
14732 }
14733 }
14734 }
14735 else
14736 {
14737 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014738 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014739 if($Level eq "Source")
14740 {
14741 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14742 { # different names
14743 return 1;
14744 }
14745 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014746
14747 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14748 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14749
14750 if($MT1{"Name"} ne $MT2{"Name"}
14751 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14752 {
14753 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14754 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14755
14756 if($PL1 ne $PL2)
14757 { # different pointer level
14758 return 1;
14759 }
14760
14761 # compare base types
14762 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14763 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14764
14765 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14766 { # different types
14767 return 1;
14768 }
14769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014770 }
14771 }
14772 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014773 else
14774 {
14775 # TODO: arrays, etc.
14776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014777 }
14778 return 0;
14779}
14780
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014781sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014782{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014783 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014784 if(not $Type1_Id or not $Type2_Id) {
14785 return ();
14786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014787 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014788 my %Type1 = get_Type($Type1_Id, 1);
14789 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014790 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14791 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014792
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030014793 if(defined $SkipTypedefUncover)
14794 {
14795 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) {
14796 return ();
14797 }
14798
14799 if(cmpBTypes($Type1_Pure{"Name"}, $Type2_Pure{"Name"}, 1, 2)) {
14800 return ();
14801 }
14802 }
14803
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014804 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14805 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 +040014806
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014807 if(defined $UsedDump{1}{"DWARF"})
14808 {
14809 if($Type1_Pure{"Name"} eq "__unknown__"
14810 or $Type2_Pure{"Name"} eq "__unknown__"
14811 or $Type1_Base{"Name"} eq "__unknown__"
14812 or $Type2_Base{"Name"} eq "__unknown__")
14813 { # Error ABI dump
14814 return ();
14815 }
14816 }
14817
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014818 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14819 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014820 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14821 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14822 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14823 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14824 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14825 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14826 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014827 if($Type1{"Name"} eq $Type2{"Name"})
14828 {
14829 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14830 { # will be reported in mergeTypes() as typedef problem
14831 return ();
14832 }
14833 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14834 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14835 if(%Typedef_1 and %Typedef_2)
14836 {
14837 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14838 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14839 { # const Typedef
14840 return ();
14841 }
14842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014843 }
14844 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14845 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014846 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014847 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14848 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014849 {
14850 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14851 "Old_Value"=>$Type1_Base{"Name"},
14852 "New_Value"=>$Type2_Base{"Name"},
14853 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014854 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014855 }
14856 else
14857 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014858 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014859 { # format change
14860 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14861 "Old_Value"=>$Type1_Base{"Name"},
14862 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014863 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014864 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 }
14866 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14867 {
14868 %{$LocalProblems{$Prefix."_BaseType"}}=(
14869 "Old_Value"=>$Type1_Base{"Name"},
14870 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014871 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014872 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014873 }
14874 }
14875 }
14876 }
14877 elsif($Type1{"Name"} ne $Type2{"Name"})
14878 { # type change
14879 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14880 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014881 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014882 and $Type1_Pure{"Name"} eq "void")
14883 {
14884 %{$LocalProblems{"Return_Type_From_Void"}}=(
14885 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014886 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014888 elsif($Prefix eq "Return"
14889 and $Type2_Pure{"Name"} eq "void")
14890 {
14891 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14892 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014893 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014895 else
14896 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014897 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014898 and $Type1{"Size"} and $Type2{"Size"}
14899 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014900 {
14901 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14902 "Old_Value"=>$Type1{"Name"},
14903 "New_Value"=>$Type2{"Name"},
14904 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014905 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014906 }
14907 else
14908 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014909 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910 { # format change
14911 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14912 "Old_Value"=>$Type1{"Name"},
14913 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014914 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014915 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014916 }
14917 elsif(tNameLock($Type1_Id, $Type2_Id))
14918 { # FIXME: correct this condition
14919 %{$LocalProblems{$Prefix."_Type"}}=(
14920 "Old_Value"=>$Type1{"Name"},
14921 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014922 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014923 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 }
14925 }
14926 }
14927 }
14928 }
14929 if($Type1_PLevel!=$Type2_PLevel)
14930 {
14931 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14932 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14933 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014934 if($Level eq "Source")
14935 {
14936 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 "Old_Value"=>$Type1_PLevel,
14938 "New_Value"=>$Type2_PLevel);
14939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014940 else
14941 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014942 if($Type2_PLevel>$Type1_PLevel)
14943 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014944 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14945 "Old_Value"=>$Type1_PLevel,
14946 "New_Value"=>$Type2_PLevel);
14947 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014948 else
14949 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014950 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14951 "Old_Value"=>$Type1_PLevel,
14952 "New_Value"=>$Type2_PLevel);
14953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 }
14955 }
14956 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014957 if($Type1_Pure{"Type"} eq "Array"
14958 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014959 { # base_type[N] -> base_type[N]
14960 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014961 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 foreach my $SubProblemType (keys(%SubProblems))
14963 {
14964 $SubProblemType=~s/_Type/_BaseType/g;
14965 next if(defined $LocalProblems{$SubProblemType});
14966 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14967 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14968 }
14969 }
14970 }
14971 return %LocalProblems;
14972}
14973
14974sub tNameLock($$)
14975{
14976 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014977 my $Changed = 0;
14978 if(differentDumps("G"))
14979 { # different GCC versions
14980 $Changed = 1;
14981 }
14982 elsif(differentDumps("V"))
14983 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014984 if(not checkDump(1, "2.20")
14985 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014986 { # latest names update
14987 # 2.6: added restrict qualifier
14988 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014989 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014990 $Changed = 1;
14991 }
14992 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014993
14994 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14995 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14996
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014997 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14998 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14999
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015000 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015001 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015002 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015003 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015004 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015006 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015007 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015008 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015010 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15011 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15012 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015013 { # equal base types
15014 return 0;
15015 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015016
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015017 if(not checkDump(1, "2.13")
15018 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015019 { # broken array names in ABI dumps < 2.13
15020 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015021 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 return 0;
15023 }
15024 }
15025
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015026 if(not checkDump(1, "2.6")
15027 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015028 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015029 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015030 and $TN2=~/\brestrict\b/) {
15031 return 0;
15032 }
15033 }
15034
15035 if(not checkDump(1, "2.20")
15036 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015037 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015038 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15039 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015040 return 0;
15041 }
15042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015043 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015044 else
15045 {
15046 # typedef struct {...} type_t
15047 # typedef struct type_t {...} type_t
15048 if(index($TN1, " ".$TN2)!=-1)
15049 {
15050 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15051 return 0;
15052 }
15053 }
15054 if(index($TN2, " ".$TN1)!=-1)
15055 {
15056 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15057 return 0;
15058 }
15059 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015060
15061 if($TT1 eq "FuncPtr"
15062 and $TT2 eq "FuncPtr")
15063 {
15064 my $TN1_C = $TN1;
15065 my $TN2_C = $TN2;
15066
15067 $TN1_C=~s/\b(struct|union) //g;
15068 $TN2_C=~s/\b(struct|union) //g;
15069
15070 if($TN1_C eq $TN2_C) {
15071 return 0;
15072 }
15073 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015074 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015075
15076 my ($N1, $N2) = ($TN1, $TN2);
15077 $N1=~s/\b(struct|union) //g;
15078 $N2=~s/\b(struct|union) //g;
15079
15080 if($N1 eq $N2)
15081 { # QList<struct QUrl> and QList<QUrl>
15082 return 0;
15083 }
15084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015085 return 1;
15086}
15087
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015088sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015089{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015090 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015091 if(defined $Cache{"differentDumps"}{$Check}) {
15092 return $Cache{"differentDumps"}{$Check};
15093 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015094 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015095 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015096 if($Check eq "G")
15097 {
15098 if(getGccVersion(1) ne getGccVersion(2))
15099 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015100 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015102 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015103 if($Check eq "V")
15104 {
15105 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15106 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15107 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015108 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015112 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015113}
15114
15115sub formatVersion($$)
15116{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015117 my ($V, $Digits) = @_;
15118 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015119 return join(".", splice(@Elems, 0, $Digits));
15120}
15121
15122sub htmlSpecChars($)
15123{
15124 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015125 if(not $Str) {
15126 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015128 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15129 $Str=~s/</&lt;/g;
15130 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15131 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015132 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15133 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015134 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015135 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015136 $Str=~s/\n/<br\/>/g;
15137 $Str=~s/\"/&quot;/g;
15138 $Str=~s/\'/&#39;/g;
15139 return $Str;
15140}
15141
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015142sub xmlSpecChars($)
15143{
15144 my $Str = $_[0];
15145 if(not $Str) {
15146 return $Str;
15147 }
15148
15149 $Str=~s/\&([^#]|\Z)/&amp;$1/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 Ponomarenko01117f12012-06-26 12:23:02 +040015159sub xmlSpecChars_R($)
15160{
15161 my $Str = $_[0];
15162 if(not $Str) {
15163 return $Str;
15164 }
15165
15166 $Str=~s/&amp;/&/g;
15167 $Str=~s/&lt;/</g;
15168 $Str=~s/&gt;/>/g;
15169
15170 $Str=~s/&quot;/"/g;
15171 $Str=~s/&#39;/'/g;
15172
15173 return $Str;
15174}
15175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015176sub black_name($)
15177{
15178 my $Name = $_[0];
15179 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15180}
15181
15182sub highLight_Signature($)
15183{
15184 my $Signature = $_[0];
15185 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15186}
15187
15188sub highLight_Signature_Italic_Color($)
15189{
15190 my $Signature = $_[0];
15191 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15192}
15193
15194sub separate_symbol($)
15195{
15196 my $Symbol = $_[0];
15197 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15198 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15199 ($Name, $Spec, $Ver) = ($1, $2, $3);
15200 }
15201 return ($Name, $Spec, $Ver);
15202}
15203
15204sub cut_f_attrs($)
15205{
15206 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15207 return $2;
15208 }
15209 return "";
15210}
15211
15212sub highLight_Signature_PPos_Italic($$$$$)
15213{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015214 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15215 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15217 my $Return = "";
15218 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15219 $Return = $2;
15220 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015221 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015223 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015225 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015226 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015228 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015229 }
15230 return $Signature;
15231 }
15232 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15233 $Begin.=" " if($Begin!~/ \Z/);
15234 $End = cut_f_attrs($Signature);
15235 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015236 my ($Short, $Params) = split_Signature($Signature);
15237 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015238 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015239 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015240 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015241 $Part=~s/\A\s+|\s+\Z//g;
15242 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15243 if($Part=~/\([\*]+(\w+)\)/i) {
15244 $ParamName = $1;#func-ptr
15245 }
15246 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15247 $ParamName = $1;
15248 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015249 if(not $ParamName)
15250 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015251 push(@Parts, $Part_Styled);
15252 next;
15253 }
15254 if($ItalicParams and not $TName_Tid{1}{$Part}
15255 and not $TName_Tid{2}{$Part})
15256 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015257 my $Style = "<i>$ParamName</i>";
15258
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015259 if($Param_Pos ne ""
15260 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015261 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015262 }
15263 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015264 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015266
15267 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268 }
15269 $Part_Styled=~s/,(\w)/, $1/g;
15270 push(@Parts, $Part_Styled);
15271 }
15272 if(@Parts)
15273 {
15274 foreach my $Num (0 .. $#Parts)
15275 {
15276 if($Num==$#Parts)
15277 { # add ")" to the last parameter
15278 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15279 }
15280 elsif(length($Parts[$Num])<=45) {
15281 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15282 }
15283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015284 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015285 }
15286 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015287 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 }
15289 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015290 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015292 $Signature=~s!\[\]![&#160;]!g;
15293 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015294 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15295 if($SymbolVersion) {
15296 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15297 }
15298 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015299}
15300
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015301sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015302{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015303 my $Signature = $_[0];
15304 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15305 {
15306 $Signature=~s/\A\Q$ShortName\E\(//g;
15307 cut_f_attrs($Signature);
15308 $Signature=~s/\)\Z//;
15309 return ($ShortName, $Signature);
15310 }
15311
15312 # error
15313 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015314}
15315
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015316sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015317{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015318 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015319 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015320 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15321 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322 foreach my $Pos (0 .. length($Params) - 1)
15323 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015324 my $S = substr($Params, $Pos, 1);
15325 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015326 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015327 }
15328 if($S eq "," and
15329 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015330 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015331 if($Comma)
15332 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015333 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015334 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015335 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015336 }
15337 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015338 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015339 }
15340 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015341 if(not $Sp)
15342 { # remove spaces
15343 foreach (@Parts)
15344 {
15345 s/\A //g;
15346 s/ \Z//g;
15347 }
15348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015349 return @Parts;
15350}
15351
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015352sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353{
15354 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015355 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015356 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015357 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15358 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015359 $Center+=length($1);
15360 }
15361 foreach my $Pos (0 .. length($Sign)-1)
15362 {
15363 my $S = substr($Sign, $Pos, 1);
15364 if($S eq $Target)
15365 {
15366 if($B{"("}==$B{")"}
15367 and $B{"<"}==$B{">"}) {
15368 return $Center;
15369 }
15370 }
15371 if(defined $B{$S}) {
15372 $B{$S}+=1;
15373 }
15374 $Center+=1;
15375 }
15376 return 0;
15377}
15378
15379sub appendFile($$)
15380{
15381 my ($Path, $Content) = @_;
15382 return if(not $Path);
15383 if(my $Dir = get_dirname($Path)) {
15384 mkpath($Dir);
15385 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015386 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015387 print FILE $Content;
15388 close(FILE);
15389}
15390
15391sub writeFile($$)
15392{
15393 my ($Path, $Content) = @_;
15394 return if(not $Path);
15395 if(my $Dir = get_dirname($Path)) {
15396 mkpath($Dir);
15397 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015398 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015399 print FILE $Content;
15400 close(FILE);
15401}
15402
15403sub readFile($)
15404{
15405 my $Path = $_[0];
15406 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015407 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 local $/ = undef;
15409 my $Content = <FILE>;
15410 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015411 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015412 $Content=~s/\r/\n/g;
15413 }
15414 return $Content;
15415}
15416
15417sub get_filename($)
15418{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015419 if(defined $Cache{"get_filename"}{$_[0]}) {
15420 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015422 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15423 return ($Cache{"get_filename"}{$_[0]}=$1);
15424 }
15425 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015426}
15427
15428sub get_dirname($)
15429{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015430 if(defined $Cache{"get_dirname"}{$_[0]}) {
15431 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015432 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015433 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15434 return ($Cache{"get_dirname"}{$_[0]}=$1);
15435 }
15436 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437}
15438
15439sub separate_path($) {
15440 return (get_dirname($_[0]), get_filename($_[0]));
15441}
15442
15443sub esc($)
15444{
15445 my $Str = $_[0];
15446 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15447 return $Str;
15448}
15449
15450sub readLineNum($$)
15451{
15452 my ($Path, $Num) = @_;
15453 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015454 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015455 foreach (1 ... $Num) {
15456 <FILE>;
15457 }
15458 my $Line = <FILE>;
15459 close(FILE);
15460 return $Line;
15461}
15462
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015463sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015464{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015465 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015466 return () if(not $Path or not -f $Path);
15467 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015468 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15469 {
15470 foreach my $AttrVal (split(/;/, $1))
15471 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015472 if($AttrVal=~/(.+):(.+)/)
15473 {
15474 my ($Name, $Value) = ($1, $2);
15475 $Attributes{$Name} = $Value;
15476 }
15477 }
15478 }
15479 return \%Attributes;
15480}
15481
15482sub is_abs($) {
15483 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15484}
15485
15486sub get_abs_path($)
15487{ # abs_path() should NOT be called for absolute inputs
15488 # because it can change them
15489 my $Path = $_[0];
15490 if(not is_abs($Path)) {
15491 $Path = abs_path($Path);
15492 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030015493 return path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015494}
15495
15496sub get_OSgroup()
15497{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015498 my $N = $Config{"osname"};
15499 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015500 return "macos";
15501 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015502 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015503 return "bsd";
15504 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015505 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015506 return "beos";
15507 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015508 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015509 return "symbian";
15510 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015511 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015512 return "windows";
15513 }
15514 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015515 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 }
15517}
15518
15519sub getGccVersion($)
15520{
15521 my $LibVersion = $_[0];
15522 if($GCC_VERSION{$LibVersion})
15523 { # dump version
15524 return $GCC_VERSION{$LibVersion};
15525 }
15526 elsif($UsedDump{$LibVersion}{"V"})
15527 { # old-version dumps
15528 return "unknown";
15529 }
15530 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15531 if(not $GccVersion) {
15532 return "unknown";
15533 }
15534 return $GccVersion;
15535}
15536
15537sub showArch($)
15538{
15539 my $Arch = $_[0];
15540 if($Arch eq "arm"
15541 or $Arch eq "mips") {
15542 return uc($Arch);
15543 }
15544 return $Arch;
15545}
15546
15547sub getArch($)
15548{
15549 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015550
15551 if($TargetArch) {
15552 return $TargetArch;
15553 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015554 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015555 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015556 return $CPU_ARCH{$LibVersion};
15557 }
15558 elsif($UsedDump{$LibVersion}{"V"})
15559 { # old-version dumps
15560 return "unknown";
15561 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015562
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015563 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015564}
15565
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015566sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015567{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015568 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015569
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015570 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015571 if(getArch(1) ne getArch(2)
15572 or getArch(1) eq "unknown"
15573 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 { # don't show architecture in the header
15575 $ArchInfo="";
15576 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015577 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015578 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015579 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015580 }
15581 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015582 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015583 }
15584 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015585 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015586 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015587
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015588 my $V1 = $Descriptor{1}{"Version"};
15589 my $V2 = $Descriptor{2}{"Version"};
15590
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015591 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15592 {
15593 my $M1 = $UsedDump{1}{"M"};
15594 my $M2 = $UsedDump{2}{"M"};
15595
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015596 my $M1S = $M1;
15597 my $M2S = $M2;
15598
15599 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15600 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15601
15602 if($M1S eq $M2S
15603 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015604 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015605 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15606 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015607 }
15608 else
15609 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015610 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15611 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015612 }
15613 }
15614 else
15615 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015616 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015617 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015618 }
15619
15620 $Title .= $ArchInfo;
15621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015622 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015623 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015624 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015625 $Title = "<h1>".$Title."</h1>\n";
15626 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627}
15628
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015629sub get_CheckedHeaders($)
15630{
15631 my $LibVersion = $_[0];
15632
15633 my @Headers = ();
15634
15635 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15636 {
15637 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015638
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015639 if(not is_target_header($File, $LibVersion)) {
15640 next;
15641 }
15642
15643 if(skipHeader($File, $LibVersion)) {
15644 next;
15645 }
15646
15647 push(@Headers, $Path);
15648 }
15649
15650 return @Headers;
15651}
15652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015653sub get_SourceInfo()
15654{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015655 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015656
15657 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015659 $CheckedHeaders = "<a name='Headers'></a>";
15660 if($OldStyle) {
15661 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15662 }
15663 else {
15664 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15665 }
15666 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015667 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 +040015668 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015669 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15670 my $Name = get_filename($Identity);
15671 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15672 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015673 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015674 $CheckedHeaders .= "</div>\n";
15675 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015676 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015677
15678 if(my @Sources = keys(%{$Registered_Sources{1}}))
15679 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015680 $CheckedSources = "<a name='Sources'></a>";
15681 if($OldStyle) {
15682 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15683 }
15684 else {
15685 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15686 }
15687 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015688 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15689 {
15690 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15691 my $Name = get_filename($Identity);
15692 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15693 $CheckedSources .= $Name.$Comment."<br/>\n";
15694 }
15695 $CheckedSources .= "</div>\n";
15696 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15697 }
15698
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015699 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015700 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015701 $CheckedLibs = "<a name='Libs'></a>";
15702 if($OldStyle) {
15703 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15704 }
15705 else {
15706 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15707 }
15708 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15709 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015710 $CheckedLibs .= $Library."<br/>\n";
15711 }
15712 $CheckedLibs .= "</div>\n";
15713 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015715
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015716 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15717}
15718
15719sub get_ObjTitle()
15720{
15721 if(defined $UsedDump{1}{"DWARF"}) {
15722 return "Objects";
15723 }
15724 else {
15725 return ucfirst($SLIB_TYPE)." Libraries";
15726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015727}
15728
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015729sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015730{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015731 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015732 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015733
15734 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 {
15736 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015737 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015739 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015740 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015741 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015742 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015743
15744 if($Severity ne $TargetSeverity) {
15745 next;
15746 }
15747
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015748 if($Kinds_Target{$Kind}{$Target}) {
15749 next;
15750 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 $Kinds_Target{$Kind}{$Target} = 1;
15753 $Type_Problems_Count += 1;
15754 }
15755 }
15756 }
15757 return $Type_Problems_Count;
15758}
15759
15760sub get_Summary($)
15761{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015762 my $Level = $_[0];
15763 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015764 $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 +040015765 %{$RESULT{$Level}} = (
15766 "Problems"=>0,
15767 "Warnings"=>0,
15768 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015770 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015771 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015772 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015773 {
15774 if(not defined $CompatRules{$Level}{$Kind})
15775 { # unknown rule
15776 if(not $UnknownRules{$Level}{$Kind})
15777 { # only one warning
15778 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15779 $UnknownRules{$Level}{$Kind}=1;
15780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015781 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 }
15783 }
15784 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015785 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15786 {
15787 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15788 {
15789 if(not defined $CompatRules{$Level}{$Kind})
15790 { # unknown rule
15791 if(not $UnknownRules{$Level}{$Kind})
15792 { # only one warning
15793 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15794 $UnknownRules{$Level}{$Kind}=1;
15795 }
15796 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15797 }
15798 }
15799 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015800 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015802 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015803 {
15804 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15805 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015806 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015808 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015809 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015810 $Added += 1;
15811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015812 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015813 {
15814 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015815 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015816 }
15817 else
15818 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015819 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 $I_Other += 1;
15821 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015822 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015823 $I_Problems_High += 1;
15824 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015825 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 $I_Problems_Medium += 1;
15827 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015828 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015829 $I_Problems_Low += 1;
15830 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015831 if(($Severity ne "Low" or $StrictCompat)
15832 and $Severity ne "Safe") {
15833 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015834 }
15835 }
15836 }
15837 }
15838 }
15839 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015840
15841 my %MethodTypeIndex = ();
15842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015843 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015844 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015845 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15846 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015847 {
15848 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15849 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015850 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15851 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015852 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015853 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15854 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015855
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015856 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15857 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015858 next;
15859 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015860 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15861 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15862
15863 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015864
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015865 if(($Severity ne "Low" or $StrictCompat)
15866 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015867 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015868 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015869 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015870 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015871 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015872 }
15873 }
15874 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015875 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015878 }
15879 }
15880 }
15881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015882
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015883 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15884 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15885 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15886 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015887
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015888 # changed and removed public symbols
15889 my $SCount = keys(%{$CheckedSymbols{$Level}});
15890 if($ExtendedCheck)
15891 { # don't count external_func_0 for constants
15892 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015894 if($SCount)
15895 {
15896 my %Weight = (
15897 "High" => 100,
15898 "Medium" => 50,
15899 "Low" => 25
15900 );
15901 foreach (keys(%{$TotalAffected{$Level}})) {
15902 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015903 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015904 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015905 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015906 else {
15907 $RESULT{$Level}{"Affected"} = 0;
15908 }
15909
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015910 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15911 if($RESULT{$Level}{"Affected"}>=100) {
15912 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015913 }
15914
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015915 $RESULT{$Level}{"Problems"} += $Removed;
15916 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015917 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015918 if($StrictCompat) {
15919 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15920 }
15921 else {
15922 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015924
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015925 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015926 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015927 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015928 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015929 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015930 if($Severity eq "Safe")
15931 {
15932 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015933 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015934 elsif($Severity eq "Low")
15935 {
15936 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015939 }
15940
15941 if($C_Problems_Low)
15942 {
15943 if($StrictCompat) {
15944 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15945 }
15946 else {
15947 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015948 }
15949 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015950 if($RESULT{$Level}{"Problems"}
15951 and $RESULT{$Level}{"Affected"}) {
15952 $RESULT{$Level}{"Verdict"} = "incompatible";
15953 }
15954 else {
15955 $RESULT{$Level}{"Verdict"} = "compatible";
15956 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015957
15958 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15959 if(not $TotalTypes)
15960 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961 $TotalTypes = keys(%{$TName_Tid{1}});
15962 }
15963
15964 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15965 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15966
15967 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15968
15969 if($ReportFormat eq "xml")
15970 { # XML
15971 # test info
15972 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15973 $TestInfo .= " <version1>\n";
15974 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015975 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015976 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15977 $TestInfo .= " </version1>\n";
15978
15979 $TestInfo .= " <version2>\n";
15980 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015981 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015982 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15983 $TestInfo .= " </version2>\n";
15984 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15985
15986 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015987 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015989 $TestResults .= " <headers>\n";
15990 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15991 {
15992 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15993 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15994 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15995 }
15996 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015998
15999 if(my @Sources = keys(%{$Registered_Sources{1}}))
16000 {
16001 $TestResults .= " <sources>\n";
16002 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
16003 {
16004 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
16005 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
16006 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
16007 }
16008 $TestResults .= " </sources>\n";
16009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016010
16011 $TestResults .= " <libs>\n";
16012 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
16013 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016014 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 $TestResults .= " <name>$Library</name>\n";
16016 }
16017 $TestResults .= " </libs>\n";
16018
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016019 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016020 $TestResults .= " <types>".$TotalTypes."</types>\n";
16021
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016022 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
16023 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016024 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16025
16026 # problem summary
16027 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16028 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16029
16030 $Problem_Summary .= " <problems_with_types>\n";
16031 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16032 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16033 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16034 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16035 $Problem_Summary .= " </problems_with_types>\n";
16036
16037 $Problem_Summary .= " <problems_with_symbols>\n";
16038 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16039 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16040 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016041 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016042 $Problem_Summary .= " </problems_with_symbols>\n";
16043
16044 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016045 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016046 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016048 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16049
16050 return ($TestInfo.$TestResults.$Problem_Summary, "");
16051 }
16052 else
16053 { # HTML
16054 # test info
16055 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016056 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016057
16058 if($TargetComponent eq "library") {
16059 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16060 }
16061 else {
16062 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016064
16065 my (@VInf1, @VInf2, $AddTestInfo) = ();
16066 if($Arch1 ne "unknown"
16067 and $Arch2 ne "unknown")
16068 { # CPU arch
16069 if($Arch1 eq $Arch2)
16070 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016071 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016072 }
16073 else
16074 { # go to the version number
16075 push(@VInf1, showArch($Arch1));
16076 push(@VInf2, showArch($Arch2));
16077 }
16078 }
Andrey Ponomarenko8580e852016-08-19 19:11:48 +030016079 if($Level eq "Binary"
16080 and $GccV1 ne "unknown"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016081 and $GccV2 ne "unknown"
16082 and $OStarget ne "windows")
16083 { # GCC version
16084 if($GccV1 eq $GccV2)
16085 { # go to the separate section
16086 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16087 }
16088 else
16089 { # go to the version number
16090 push(@VInf1, "gcc ".$GccV1);
16091 push(@VInf2, "gcc ".$GccV2);
16092 }
16093 }
16094 # show long version names with GCC version and CPU architecture name (if different)
16095 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16096 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16097 $TestInfo .= $AddTestInfo;
16098 #if($COMMON_LANGUAGE{1}) {
16099 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16100 #}
16101 if($ExtendedCheck) {
16102 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016104 if($JoinReport)
16105 {
16106 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016107 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016108 }
16109 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016110 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016111 }
16112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016113 $TestInfo .= "</table>\n";
16114
16115 # test results
16116 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016117 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016118
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016119 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016120 {
16121 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16122 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16123 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016124
16125 if(my @Sources = keys(%{$Registered_Sources{1}}))
16126 {
16127 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16128 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016130
16131 if(not $ExtendedCheck)
16132 {
16133 my $Libs_Link = "0";
16134 $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 +040016135 $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 +040016136 }
16137
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016138 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016139
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016140 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016141 if($JoinReport) {
16142 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16143 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016144
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016145 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016146
16147 $TestResults .= "<tr><th>Compatibility</th>\n";
16148 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16149 {
16150 my $Cl = "incompatible";
16151 if($BC_Rate>=90) {
16152 $Cl = "warning";
16153 }
16154 elsif($BC_Rate>=80) {
16155 $Cl = "almost_compatible";
16156 }
16157
16158 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016159 }
16160 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016161 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016162 }
16163 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164 $TestResults .= "</table>\n";
16165
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016166 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167 # problem summary
16168 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016169 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16171
16172 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016173 if($Added>0)
16174 {
16175 if($JoinReport) {
16176 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16177 }
16178 else {
16179 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16180 }
16181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016182 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016183 $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 +040016184
16185 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016186 if($Removed>0)
16187 {
16188 if($JoinReport) {
16189 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16190 }
16191 else {
16192 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16193 }
16194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016196 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016197 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016198
16199 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016200 $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 +040016201 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016202 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016203 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204
16205 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016206 $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 +040016207 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016208 $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 +040016209
16210 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016211 $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 +040016212 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016213 $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 +040016214
16215 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016216 $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 +040016217 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016218 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016219 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016220
16221 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016222 $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 +040016223 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016224 $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 +040016225
16226 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016227 $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 +040016228 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016229 $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 +040016230
16231 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016232 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16233 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016234 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016235 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016236 $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 +040016237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016238 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016239 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016240 {
16241 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016242 $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 +030016243 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016246 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 {
16248 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016249 $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 +030016250 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016252
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016253 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016254 {
16255 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016256 $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 +030016257 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016258 }
16259
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 $META_DATA .= "tool_version:$TOOL_VERSION";
16261 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016263 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16264 }
16265}
16266
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016267sub getStyle($$$)
16268{
16269 my ($Subj, $Act, $Num) = @_;
16270 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016271 "Added"=>"new",
16272 "Removed"=>"failed",
16273 "Safe"=>"passed",
16274 "Low"=>"warning",
16275 "Medium"=>"failed",
16276 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016277 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016278
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016279 if($Num>0) {
16280 return " class='".$Style{$Act}."'";
16281 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016282
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016283 return "";
16284}
16285
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286sub show_number($)
16287{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016288 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016290 my $Num = cut_off_number($_[0], 2, 0);
16291 if($Num eq "0")
16292 {
16293 foreach my $P (3 .. 7)
16294 {
16295 $Num = cut_off_number($_[0], $P, 1);
16296 if($Num ne "0") {
16297 last;
16298 }
16299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 }
16301 if($Num eq "0") {
16302 $Num = $_[0];
16303 }
16304 return $Num;
16305 }
16306 return $_[0];
16307}
16308
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016309sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 if($num!~/\./)
16313 {
16314 $num .= ".";
16315 foreach (1 .. $digs_to_cut-1) {
16316 $num .= "0";
16317 }
16318 }
16319 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16320 {
16321 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16322 $num .= "0";
16323 }
16324 }
16325 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16326 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16327 }
16328 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016329 if($z) {
16330 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016332 return $num;
16333}
16334
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016335sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016336{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016337 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016338 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016339
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016340 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016341 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16342 {
16343 my $Header = $Constants{1}{$Constant}{"Header"};
16344 if(not $Header)
16345 { # added
16346 $Header = $Constants{2}{$Constant}{"Header"}
16347 }
16348
16349 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16350 {
16351 if(not defined $CompatRules{$Level}{$Kind}) {
16352 next;
16353 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016354 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016355 next;
16356 }
16357 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016359 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 if($ReportFormat eq "xml")
16362 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016363 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 {
16365 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016366 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016367 {
16368 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016369 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16370 {
16371 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16372 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16373 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016374
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016375 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16376 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16377 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016378 if($Overcome) {
16379 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16380 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016381 $CHANGED_CONSTANTS .= " </problem>\n";
16382 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 $CHANGED_CONSTANTS .= " </constant>\n";
16384 }
16385 $CHANGED_CONSTANTS .= " </header>\n";
16386 }
16387 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16388 }
16389 else
16390 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016391 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016392 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016393 {
16394 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016395 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016397 my $Report = "";
16398
16399 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16400 {
16401 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16402 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016403 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016404 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016405 }
16406 if($Report)
16407 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016408 $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 +030016409 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016410 $Report = insertIDs($Report);
16411 }
16412 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016413 }
16414 $CHANGED_CONSTANTS .= "<br/>\n";
16415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 if($CHANGED_CONSTANTS)
16417 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016418 my $Title = "Problems with Constants, $TargetSeverity Severity";
16419 if($TargetSeverity eq "Safe")
16420 { # Safe Changes
16421 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016422 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016423 if($OldStyle) {
16424 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16425 }
16426 else {
16427 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16428 }
16429 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016430 }
16431 }
16432 return $CHANGED_CONSTANTS;
16433}
16434
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016435sub getTitle($$$)
16436{
16437 my ($Header, $Library, $NameSpace) = @_;
16438 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016439
16440 # if($Library and $Library!~/\.\w+\Z/) {
16441 # $Library .= " (.$LIB_EXT)";
16442 # }
16443
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016444 if($Header and $Library)
16445 {
16446 $Title .= "<span class='h_name'>$Header</span>";
16447 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16448 }
16449 elsif($Library) {
16450 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16451 }
16452 elsif($Header) {
16453 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16454 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016455
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016456 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016457 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016458 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016459
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016460 return $Title;
16461}
16462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016463sub get_Report_Added($)
16464{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016465 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016466 my $ADDED_INTERFACES = "";
16467 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016468 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016472 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473 {
16474 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16475 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 if($Level eq "Source" and $ReportFormat eq "html")
16477 { # do not show library name in HTML report
16478 $DyLib = "";
16479 }
16480 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 }
16482 }
16483 }
16484 if($ReportFormat eq "xml")
16485 { # XML
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 {
16488 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016489 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 {
16491 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016492 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016493 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16494 }
16495 $ADDED_INTERFACES .= " </library>\n";
16496 }
16497 $ADDED_INTERFACES .= " </header>\n";
16498 }
16499 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16500 }
16501 else
16502 { # HTML
16503 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016504 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016505 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016506 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016507 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016508 my %NameSpaceSymbols = ();
16509 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016510 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016512 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16515 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 foreach my $Interface (@SortedInterfaces)
16517 {
16518 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016519 my $Signature = get_Signature($Interface, 2);
16520 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016521 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016522 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016523 if($Interface=~/\A(_Z|\?)/)
16524 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016526 $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 +040016527 }
16528 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016529 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 }
16531 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016532 else
16533 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016534 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016535 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 }
16537 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016538 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016539 }
16540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016542 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 }
16545 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016546 if($ADDED_INTERFACES)
16547 {
16548 my $Anchor = "<a name='Added'></a>";
16549 if($JoinReport) {
16550 $Anchor = "<a name='".$Level."_Added'></a>";
16551 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016552 if($OldStyle) {
16553 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16554 }
16555 else {
16556 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16557 }
16558 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016559 }
16560 }
16561 return $ADDED_INTERFACES;
16562}
16563
16564sub get_Report_Removed($)
16565{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016566 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016567 my $REMOVED_INTERFACES = "";
16568 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016569 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016570 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016571 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016575 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16576 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 if($Level eq "Source" and $ReportFormat eq "html")
16578 { # do not show library name in HTML report
16579 $DyLib = "";
16580 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016581 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016582 }
16583 }
16584 }
16585 if($ReportFormat eq "xml")
16586 { # XML
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 {
16589 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016590 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 {
16592 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016593 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16594 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 }
16596 $REMOVED_INTERFACES .= " </library>\n";
16597 }
16598 $REMOVED_INTERFACES .= " </header>\n";
16599 }
16600 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16601 }
16602 else
16603 { # HTML
16604 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016605 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016606 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016607 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016608 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 my %NameSpaceSymbols = ();
16610 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016611 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016612 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016613 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016614 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016615 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16616 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016617 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 {
16619 $Removed_Number += 1;
16620 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016621 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016623 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016624 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016625 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016626 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016628 $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 +040016629 }
16630 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016631 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 }
16633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 else
16635 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016636 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016637 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016638 }
16639 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016640 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 }
16642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016643 }
16644 }
16645 $REMOVED_INTERFACES .= "<br/>\n";
16646 }
16647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016648 if($REMOVED_INTERFACES)
16649 {
16650 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16651 if($JoinReport) {
16652 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16653 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016654 if($OldStyle) {
16655 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16656 }
16657 else {
16658 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16659 }
16660
16661 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016662 }
16663 }
16664 return $REMOVED_INTERFACES;
16665}
16666
16667sub getXmlParams($$)
16668{
16669 my ($Content, $Problem) = @_;
16670 return "" if(not $Content or not $Problem);
16671 my %XMLparams = ();
16672 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16673 {
16674 my $Macro = "\@".lc($Attr);
16675 if($Content=~/\Q$Macro\E/) {
16676 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16677 }
16678 }
16679 my @PString = ();
16680 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016681 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 }
16683 if(@PString) {
16684 return " ".join(" ", @PString);
16685 }
16686 else {
16687 return "";
16688 }
16689}
16690
16691sub addMarkup($)
16692{
16693 my $Content = $_[0];
16694 # auto-markup
16695 $Content=~s/\n[ ]*//; # spaces
16696 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16697 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016698 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16700 if($Content=~/\ANOTE:/)
16701 { # notes
16702 $Content=~s!(NOTE):!<b>$1</b>:!g;
16703 }
16704 else {
16705 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16706 }
16707 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16708 my @Keywords = (
16709 "void",
16710 "const",
16711 "static",
16712 "restrict",
16713 "volatile",
16714 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016715 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016716 );
16717 my $MKeys = join("|", @Keywords);
16718 foreach (@Keywords) {
16719 $MKeys .= "|non-".$_;
16720 }
16721 $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 +040016722
16723 # Markdown
16724 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16725 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 return $Content;
16727}
16728
16729sub applyMacroses($$$$)
16730{
16731 my ($Level, $Kind, $Content, $Problem) = @_;
16732 return "" if(not $Content or not $Problem);
16733 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16734 $Content = addMarkup($Content);
16735 # macros
16736 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16737 {
16738 my $Macro = "\@".lc($Attr);
16739 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016740 if(not defined $Value
16741 or $Value eq "") {
16742 next;
16743 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016744
16745 if(index($Content, $Macro)==-1) {
16746 next;
16747 }
16748
16749 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16750 and $Kind!~/_Type_/
16751 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016752 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016754 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016755 $Value = black_name($Value);
16756 }
16757 elsif($Value=~/\s/) {
16758 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16759 }
16760 elsif($Value=~/\A\d+\Z/
16761 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16762 { # bits to bytes
16763 if($Value % $BYTE_SIZE)
16764 { # bits
16765 if($Value==1) {
16766 $Value = "<b>".$Value."</b> bit";
16767 }
16768 else {
16769 $Value = "<b>".$Value."</b> bits";
16770 }
16771 }
16772 else
16773 { # bytes
16774 $Value /= $BYTE_SIZE;
16775 if($Value==1) {
16776 $Value = "<b>".$Value."</b> byte";
16777 }
16778 else {
16779 $Value = "<b>".$Value."</b> bytes";
16780 }
16781 }
16782 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016783 else
16784 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016785 $Value = "<b>".htmlSpecChars($Value)."</b>";
16786 }
16787 $Content=~s/\Q$Macro\E/$Value/g;
16788 }
16789
16790 if($Content=~/(\A|[^\@\w])\@\w/)
16791 {
16792 if(not $IncompleteRules{$Level}{$Kind})
16793 { # only one warning
16794 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16795 $IncompleteRules{$Level}{$Kind} = 1;
16796 }
16797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016798 return $Content;
16799}
16800
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016801sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016803 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016804 my $INTERFACE_PROBLEMS = "";
16805 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016806
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016807 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016808 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16810 if($SV and defined $CompatProblems{$Level}{$SN}) {
16811 next;
16812 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016813 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16814 my $DyLib = $Symbol_Library{1}{$Symbol};
16815 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16816 { # Symbol with Version
16817 $DyLib = $Symbol_Library{1}{$VSym};
16818 }
16819 if(not $DyLib)
16820 { # const global data
16821 $DyLib = "";
16822 }
16823 if($Level eq "Source" and $ReportFormat eq "html")
16824 { # do not show library name in HTML report
16825 $DyLib = "";
16826 }
16827
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016828 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016829 {
16830 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016831 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016832 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016833 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16834 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016835 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016836 if($Severity eq $TargetSeverity)
16837 {
16838 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16839 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 }
16841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016842 }
16843 }
16844 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016845
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 if($ReportFormat eq "xml")
16847 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016848 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016849 {
16850 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016851 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016852 {
16853 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016854 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16855 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 {
16857 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016858 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016859 {
16860 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16861 {
16862 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016863 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016865 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16866 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16867 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16868 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16869 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016870 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16871 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016873 $INTERFACE_PROBLEMS .= " </problem>\n";
16874 }
16875 }
16876 $INTERFACE_PROBLEMS .= " </symbol>\n";
16877 }
16878 $INTERFACE_PROBLEMS .= " </library>\n";
16879 }
16880 $INTERFACE_PROBLEMS .= " </header>\n";
16881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016882 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016883 }
16884 else
16885 { # HTML
16886 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016887 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016888 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016889 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 my (%NameSpaceSymbols, %NewSignature) = ();
16892 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016893 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016897 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016898 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 +040016899 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016901 my $Signature = get_Signature($Symbol, 1);
16902 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016904 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016905 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016906 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016908 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016909 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 }
16913 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16914 {
16915 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016916 $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 +040016917 $ProblemNum += 1;
16918 $ProblemsNum += 1;
16919 }
16920 }
16921 }
16922 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016923 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016924 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016925 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016927 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016928 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016929
16930 if($NameSpace)
16931 {
16932 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16933 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016935
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016936 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
16937 if($OldStyle) {
16938 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
16939 }
16940 else {
16941 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
16942 }
16943 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016944 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016945
16946 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016947 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016948 if($NameSpace) {
16949 $NSign = cut_Namespace($NSign, $NameSpace);
16950 }
16951 $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 +040016952 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016953
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016954 if($Symbol=~/\A(_Z|\?)/) {
16955 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16956 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016957
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016958 $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 +040016959 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 }
16961 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016962 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016963 }
16964 }
16965 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016966
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 if($INTERFACE_PROBLEMS)
16968 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16970 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16971 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 { # Safe Changes
16973 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016975 if($OldStyle) {
16976 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
16977 }
16978 else {
16979 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
16980 }
16981 $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 +040016982 }
16983 }
16984 return $INTERFACE_PROBLEMS;
16985}
16986
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016987sub cut_Namespace($$)
16988{
16989 my ($N, $Ns) = @_;
16990 $N=~s/\b\Q$Ns\E:://g;
16991 return $N;
16992}
16993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994sub get_Report_TypeProblems($$)
16995{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016996 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016997 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016998
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016999 my %ReportMap = ();
17000 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017001
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017002 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017003 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017004 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
17005
17006 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017008 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017009 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017010 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017011 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017012
17013 if($Severity eq $TargetSeverity)
17014 {
17015 $ReportMap{$HeaderName}{$TypeName} = 1;
17016 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017018 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017020 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017022 if($ReportFormat eq "xml")
17023 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 {
17026 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017027 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017029 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017030 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017031 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017033 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017034 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017035 $Kinds_Locations{$Kind}{$Location} = 1;
17036
17037 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17038 if($Kinds_Target{$Kind}{$Target}) {
17039 next;
17040 }
17041 $Kinds_Target{$Kind}{$Target} = 1;
17042
17043 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017044 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17045 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17046 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17047 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17048 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017049 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17050 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017052 $TYPE_PROBLEMS .= " </problem>\n";
17053 }
17054 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017055 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17056 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017057 $TYPE_PROBLEMS .= showVTables($TypeName);
17058 }
17059 $TYPE_PROBLEMS .= " </type>\n";
17060 }
17061 $TYPE_PROBLEMS .= " </header>\n";
17062 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017063 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017064 }
17065 else
17066 { # HTML
17067 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017068 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017070 my (%NameSpace_Type) = ();
17071 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017072 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017073 }
17074 foreach my $NameSpace (sort keys(%NameSpace_Type))
17075 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017076 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017077 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 +040017078 foreach my $TypeName (@SortedTypes)
17079 {
17080 my $ProblemNum = 1;
17081 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017082 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017083
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017084 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017085 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017086 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017087 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017088 $Kinds_Locations{$Kind}{$Location} = 1;
17089
17090 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17091 if($Kinds_Target{$Kind}{$Target}) {
17092 next;
17093 }
17094 $Kinds_Target{$Kind}{$Target} = 1;
17095
17096 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017097 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17098 {
17099 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017100 $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 +040017101 $ProblemNum += 1;
17102 $ProblemsNum += 1;
17103 }
17104 }
17105 }
17106 $ProblemNum -= 1;
17107 if($TYPE_REPORT)
17108 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017109 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017110 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017111 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017112 $ShowVTables = showVTables($TypeName);
17113 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017114
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017115 my $ShowType = show_Type($TypeName, 1, 1);
17116
17117 if($NameSpace)
17118 {
17119 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17120 $ShowType = cut_Namespace($ShowType, $NameSpace);
17121 $Affected = cut_Namespace($Affected, $NameSpace);
17122 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17123 }
17124
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017125 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17126 if($OldStyle) {
17127 $TYPE_PROBLEMS .= " ($ProblemNum)";
17128 }
17129 else {
17130 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17131 }
17132 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017133 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17134 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17135 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17136 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137 }
17138 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017139 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140 }
17141 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017142
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 if($TYPE_PROBLEMS)
17144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017145 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17146 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017147 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 { # Safe Changes
17149 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017150 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017151 if($OldStyle) {
17152 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17153 }
17154 else {
17155 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17156 }
17157 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017158 }
17159 }
17160 return $TYPE_PROBLEMS;
17161}
17162
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017163sub show_Type($$$)
17164{
17165 my ($Name, $Html, $LibVersion) = @_;
17166 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17167 $TType = lc($TType);
17168 if($TType=~/struct|union|enum/) {
17169 $Name=~s/\A\Q$TType\E //g;
17170 }
17171 if($Html) {
17172 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17173 }
17174 else {
17175 $Name = $TType." ".$Name;
17176 }
17177 return $Name;
17178}
17179
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017180sub get_Anchor($$$)
17181{
17182 my ($Kind, $Level, $Severity) = @_;
17183 if($JoinReport)
17184 {
17185 if($Severity eq "Safe") {
17186 return "Other_".$Level."_Changes_In_".$Kind."s";
17187 }
17188 else {
17189 return $Kind."_".$Level."_Problems_".$Severity;
17190 }
17191 }
17192 else
17193 {
17194 if($Severity eq "Safe") {
17195 return "Other_Changes_In_".$Kind."s";
17196 }
17197 else {
17198 return $Kind."_Problems_".$Severity;
17199 }
17200 }
17201}
17202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017203sub showVTables($)
17204{
17205 my $TypeName = $_[0];
17206 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017207 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 if(defined $Type1{"VTable"}
17209 and keys(%{$Type1{"VTable"}}))
17210 {
17211 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017212 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017213 if(defined $Type2{"VTable"}
17214 and keys(%{$Type2{"VTable"}}))
17215 {
17216 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17217 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017218 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017219 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017220 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17221 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 }
17223 my $VTABLES = "";
17224 if($ReportFormat eq "xml")
17225 { # XML
17226 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017227 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017229 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017230 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17231 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232 $VTABLES .= " </entry>\n";
17233 }
17234 $VTABLES .= " </vtable>\n\n";
17235 }
17236 else
17237 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017238 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017239 $VTABLES .= "<tr><th>Offset</th>";
17240 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017242 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017243 {
17244 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017245
17246 my $E1 = $Entries{$Index}{"E1"};
17247 my $E2 = $Entries{$Index}{"E2"};
17248
17249 if($E1 ne $E2
17250 and $E1!~/ 0x/
17251 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017253 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017254 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017255 $Color1 = " class='failed'";
17256 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 }
17258 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017259 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 }
17261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017262 $VTABLES .= "<tr><th>".$Index."</th>\n";
17263 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17264 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017265 }
17266 $VTABLES .= "</table><br/>\n";
17267 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017268 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017269 }
17270 return $VTABLES;
17271 }
17272 }
17273 return "";
17274}
17275
17276sub simpleVEntry($)
17277{
17278 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017279 if(not defined $VEntry
17280 or $VEntry eq "") {
17281 return "";
17282 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017283
17284 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017285 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17286 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17287 if($VEntry=~/\A_ZThn.+\Z/) {
17288 $VEntry = "non-virtual thunk";
17289 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017290 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017291 # support for old GCC versions
17292 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17293 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17294 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017295 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17296 return $VEntry;
17297}
17298
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017299sub adjustParamPos($$$)
17300{
17301 my ($Pos, $Symbol, $LibVersion) = @_;
17302 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17303 {
17304 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17305 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17306 {
17307 return $Pos-1;
17308 }
17309
17310 return $Pos;
17311 }
17312
17313 return undef;
17314}
17315
17316sub getParamPos($$$)
17317{
17318 my ($Name, $Symbol, $LibVersion) = @_;
17319
17320 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17321 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17322 {
17323 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17324 foreach (keys(%{$Info->{"Param"}}))
17325 {
17326 if($Info->{"Param"}{$_}{"name"} eq $Name)
17327 {
17328 return $_;
17329 }
17330 }
17331 }
17332
17333 return undef;
17334}
17335
17336sub getParamName($)
17337{
17338 my $Loc = $_[0];
17339 $Loc=~s/\->.*//g;
17340 return $Loc;
17341}
17342
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017343sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017344{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017345 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017346
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017347 my $LIMIT = 10;
17348 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017349 $LIMIT = $AffectLimit;
17350 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017351
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017352 my @Kinds = sort keys(%{$Kinds_Locations});
17353 my %KLocs = ();
17354 foreach my $Kind (@Kinds)
17355 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017356 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 +030017357 $KLocs{$Kind} = \@Locs;
17358 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017359
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017360 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017361 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017363 if(index($Symbol, "_Z")==0
17364 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017365 { # duplicated problems for C2 constructors, D2 and D0 destructors
17366 next;
17367 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017368
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017369 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017371 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017373 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017374 next;
17375 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017376
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017377 if(index($Symbol, "\@")!=-1
17378 or index($Symbol, "\$")!=-1)
17379 {
17380 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17381
17382 if($Level eq "Source")
17383 { # remove symbol version
17384 $Symbol = $SN;
17385 }
17386
17387 if($SV and defined $CompatProblems{$Level}{$SN}
17388 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17389 { # duplicated problems for versioned symbols
17390 next;
17391 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017392 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017393
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017394 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017395 if($Type_Name ne $Target_TypeName) {
17396 next;
17397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017399 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017400 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 }
17402 }
17403 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017404
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017405 %KLocs = (); # clear
17406
17407 my %SymSel = ();
17408 my $Num = 0;
17409 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017410 {
17411 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17412 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017413 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017414 {
17415 $SymSel{$Symbol}{"Loc"} = $Loc;
17416 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017417 last LOOP;
17418 }
17419 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017420
17421 $Num += 1;
17422
17423 if($Num>=$LIMIT) {
17424 last;
17425 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017426 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017428 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017430 if($ReportFormat eq "xml")
17431 { # XML
17432 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017433
17434 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017436 my $Kind = $SymSel{$Symbol}{"Kind"};
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017437 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017438
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017439 my $PName = getParamName($Loc);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030017440 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017442 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017443 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017444 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017445 $Target .= " param=\"$PName\"";
17446 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017447 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017448 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017449 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017450 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017451 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017452 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017453 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017454
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017455 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017456 $Target .= " field=\"$1\"";
17457 }
17458
17459 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017460 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461 $Affected .= " </symbol>\n";
17462 }
17463 $Affected .= " </affected>\n";
17464 }
17465 else
17466 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017467 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017468 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017469 my $Kind = $SymSel{$Symbol}{"Kind"};
17470 my $Loc = $SymSel{$Symbol}{"Loc"};
17471
17472 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017473 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017474 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017475 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17476
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017477 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017478 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017479 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017480
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017481 if(keys(%SymLocKind)>$LIMIT) {
17482 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017483 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017484
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017485 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017486 if($Affected)
17487 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017488 my $Num = keys(%SymLocKind);
17489 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017490 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017491 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017492 }
17493 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017495 return $Affected;
17496}
17497
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017498sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017499{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017500 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017501 if($L2=~/\A(retval|this)\b/
17502 and $L1!~/\A(retval|this)\b/)
17503 {
17504 if($L1!~/\-\>/) {
17505 return 1;
17506 }
17507 elsif($L2=~/\-\>/) {
17508 return 1;
17509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017510 }
17511 return 0;
17512}
17513
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017514sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017515{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017516 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017517
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017518 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017519
17520 my $Location_I = $Location;
17521 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017523 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017525 if($Kind eq "Overridden_Virtual_Method"
17526 or $Kind eq "Overridden_Virtual_Method_B") {
17527 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17528 }
17529 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17530 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017531 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017533 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17534 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017535 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17536 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017538 if($ClassName eq $Problem{"Type_Name"}) {
17539 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17540 }
17541 else {
17542 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17543 }
17544 }
17545 else
17546 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017547 my $TypeID = undef;
17548
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017549 if($Location=~/retval/)
17550 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017551 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 push(@Sentence, "Field \'".$Location."\' in return value");
17553 }
17554 else {
17555 push(@Sentence, "Return value");
17556 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017557
17558 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017559 }
17560 elsif($Location=~/this/)
17561 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017562 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017563 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17564 }
17565 else {
17566 push(@Sentence, "\'this\' pointer");
17567 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017568
17569 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570 }
17571 else
17572 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017573
17574 my $PName = getParamName($Location);
17575 my $PPos = getParamPos($PName, $Symbol, 1);
17576
17577 if(index($Location, "->")!=-1) {
17578 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017579 }
17580 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017581 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017582 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017583 if($PName) {
17584 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017585 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017586
17587 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17588 }
17589
17590 if($Location!~/this/)
17591 {
17592 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017593 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017594 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017595 push(@Sentence, "(pointer)");
17596 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017597 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017598 push(@Sentence, "(reference)");
17599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017600 }
17601 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017603 if($Location eq "this") {
17604 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17605 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017606 else
17607 {
17608 my $Location_T = $Location;
17609 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17610
17611 my $TypeID_Problem = $TypeID;
17612 if($Location_T) {
17613 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17614 }
17615
17616 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17617 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17618 }
17619 else {
17620 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017622 }
17623 }
17624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017625 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017626 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 +040017627 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017628
17629 my $Sent = join(" ", @Sentence);
17630
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017631 $Sent=~s/->/./g;
17632
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017633 if($ReportFormat eq "xml")
17634 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017635 $Sent=~s/'//g;
17636 }
17637
17638 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017639}
17640
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017641sub getFieldType($$$)
17642{
17643 my ($Location, $TypeId, $LibVersion) = @_;
17644
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017645 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017646
17647 foreach my $Name (@Fields)
17648 {
17649 my %Info = get_BaseType($TypeId, $LibVersion);
17650
17651 foreach my $Pos (keys(%{$Info{"Memb"}}))
17652 {
17653 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17654 {
17655 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17656 last;
17657 }
17658 }
17659 }
17660
17661 return $TypeId;
17662}
17663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017664sub get_XmlSign($$)
17665{
17666 my ($Symbol, $LibVersion) = @_;
17667 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17668 my $Report = "";
17669 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17670 {
17671 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017672 my $Type = $Info->{"Param"}{$Pos}{"type"};
17673 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017674 foreach my $Typedef (keys(%ChangedTypedef))
17675 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017676 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17677 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017679 }
17680 $Report .= " <param pos=\"$Pos\">\n";
17681 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017682 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017683 $Report .= " </param>\n";
17684 }
17685 if(my $Return = $Info->{"Return"})
17686 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017687 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017688 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017689 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017690 $Report .= " </retval>\n";
17691 }
17692 return $Report;
17693}
17694
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017695sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017696{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017697 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017698 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017699 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017700 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017701 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17702 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017703 next;
17704 }
17705 $Report .= " <symbol name=\"$Symbol\">\n";
17706 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017707 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017708 {
17709 if(defined $CompleteSignature{1}{$Symbol}
17710 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17711 {
17712 $P1 = get_XmlSign($Symbol, 1);
17713 $S1 = get_Signature($Symbol, 1);
17714 }
17715 elsif($Symbol=~/\A(_Z|\?)/) {
17716 $S1 = $tr_name{$Symbol};
17717 }
17718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017719 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017720 {
17721 if(defined $CompleteSignature{2}{$Symbol}
17722 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17723 {
17724 $P2 = get_XmlSign($Symbol, 2);
17725 $S2 = get_Signature($Symbol, 2);
17726 }
17727 elsif($Symbol=~/\A(_Z|\?)/) {
17728 $S2 = $tr_name{$Symbol};
17729 }
17730 }
17731 if($S1)
17732 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017733 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017734 $Report .= $P1;
17735 $Report .= " </old>\n";
17736 }
17737 if($S2 and $S2 ne $S1)
17738 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017739 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017740 $Report .= $P2;
17741 $Report .= " </new>\n";
17742 }
17743 $Report .= " </symbol>\n";
17744 }
17745 $Report .= "</symbols_info>\n";
17746 return $Report;
17747}
17748
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017749sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017750{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017751 my ($Level, $Report) = @_;
17752 if($ReportFormat eq "xml") {
17753 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017754 }
17755 if($StdOut)
17756 { # --stdout option
17757 print STDOUT $Report;
17758 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017759 else
17760 {
17761 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017762 mkpath(get_dirname($RPath));
17763
17764 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17765 print REPORT $Report;
17766 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017767 }
17768}
17769
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017770sub getReport($)
17771{
17772 my $Level = $_[0];
17773 if($ReportFormat eq "xml")
17774 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017775 if($Level eq "Join")
17776 {
17777 my $Report = "<reports>\n";
17778 $Report .= getReport("Binary");
17779 $Report .= getReport("Source");
17780 $Report .= "</reports>\n";
17781 return $Report;
17782 }
17783 else
17784 {
17785 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17786 my ($Summary, $MetaData) = get_Summary($Level);
17787 $Report .= $Summary."\n";
17788 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17789 $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 +040017790
17791 # additional symbols info (if needed)
17792 # $Report .= get_Report_SymbolsInfo($Level);
17793
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017794 $Report .= "</report>\n";
17795 return $Report;
17796 }
17797 }
17798 else
17799 { # HTML
17800 my $CssStyles = readModule("Styles", "Report.css");
17801 my $JScripts = readModule("Scripts", "Sections.js");
17802 if($Level eq "Join")
17803 {
17804 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17805 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017806 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017807 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17808 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 +040017809 my ($BSummary, $BMetaData) = get_Summary("Binary");
17810 my ($SSummary, $SMetaData) = get_Summary("Source");
17811 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 +030017812 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017813 <br/>
17814 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017815 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17816 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017817 </div>";
17818 $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>";
17819 $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 +030017820 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017821 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017822 return $Report;
17823 }
17824 else
17825 {
17826 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017827 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17828 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17829 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 +040017830 if($Level eq "Binary")
17831 {
17832 if(getArch(1) eq getArch(2)
17833 and getArch(1) ne "unknown") {
17834 $Description .= " on ".showArch(getArch(1));
17835 }
17836 }
17837 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 +030017838 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017839 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17840 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17841 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017842 $Report .= "</div>\n<br/><br/><br/>\n";
17843 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017844 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017845 return $Report;
17846 }
17847 }
17848}
17849
17850sub createReport()
17851{
17852 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017853 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017854 writeReport("Join", getReport("Join"));
17855 }
17856 elsif($DoubleReport)
17857 { # default
17858 writeReport("Binary", getReport("Binary"));
17859 writeReport("Source", getReport("Source"));
17860 }
17861 elsif($BinaryOnly)
17862 { # --binary
17863 writeReport("Binary", getReport("Binary"));
17864 }
17865 elsif($SourceOnly)
17866 { # --source
17867 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017868 }
17869}
17870
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017871sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017872{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017873 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017874
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017875 $Footer .= "<hr/>\n";
17876 $Footer .= "<div class='footer' align='right'>";
17877 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17878 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017879 $Footer .= "<br/>\n";
17880
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017881 return $Footer;
17882}
17883
17884sub get_Report_Problems($$)
17885{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017886 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017887
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017888 my $Report = get_Report_TypeProblems($Severity, $Level);
17889 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017890 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017891 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017892
17893 if($Severity eq "Low" or $Severity eq "Safe") {
17894 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017895 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017897 if($ReportFormat eq "html")
17898 {
17899 if($Report)
17900 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017901 if($JoinReport)
17902 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017903 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017904 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17905 }
17906 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017907 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017910 else
17911 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017912 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017913 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17914 }
17915 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017916 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017918 }
17919 }
17920 }
17921 return $Report;
17922}
17923
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017924sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017925{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017926 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017927
17928 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17929 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17930 $Head .= "<head>\n";
17931 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17932 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17933 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17934 $Head .= "<title>$Title</title>\n";
17935 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17936 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17937 $Head .= "</head>\n";
17938
17939 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017940}
17941
17942sub insertIDs($)
17943{
17944 my $Text = $_[0];
17945 while($Text=~/CONTENT_ID/)
17946 {
17947 if(int($Content_Counter)%2) {
17948 $ContentID -= 1;
17949 }
17950 $Text=~s/CONTENT_ID/c_$ContentID/;
17951 $ContentID += 1;
17952 $Content_Counter += 1;
17953 }
17954 return $Text;
17955}
17956
17957sub checkPreprocessedUnit($)
17958{
17959 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017960 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017961 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017962 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017963
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017964 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017965 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017966 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017967 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017968 chomp($Line);
17969 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017970 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017971 $CurHeader = path_format($1, $OSgroup);
17972 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017973 $CurClass = "";
17974
17975 if(index($CurHeader, $TMP_DIR)==0) {
17976 next;
17977 }
17978
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017979 if(substr($CurHeaderName, 0, 1) eq "<")
17980 { # <built-in>, <command-line>, etc.
17981 $CurHeaderName = "";
17982 $CurHeader = "";
17983 }
17984
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017985 if($ExtraInfo)
17986 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017987 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017988 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17989 }
17990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017991 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017992 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017993 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017994 if($CurHeaderName)
17995 {
17996 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17997 and not $Registered_Headers{$Version}{$CurHeader})
17998 { # not a target
17999 next;
18000 }
18001 if(not is_target_header($CurHeaderName, 1)
18002 and not is_target_header($CurHeaderName, 2))
18003 { # user-defined header
18004 next;
18005 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018006 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018007 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018008
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018009 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018010 {
18011 my ($Name, $Value) = ($1, $2);
18012 if(not $Constants{$Version}{$Name}{"Access"})
18013 {
18014 $Constants{$Version}{$Name}{"Access"} = "public";
18015 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018016 if($CurHeaderName) {
18017 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18018 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018019 }
18020 }
18021 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18022 $Constants{$Version}{$1}{"Access"} = "private";
18023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018024 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018025 else
18026 {
18027 if(defined $ExtraDump)
18028 {
18029 if($Line=~/(\w+)\s*\(/)
18030 { # functions
18031 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18032 }
18033 #elsif($Line=~/(\w+)\s*;/)
18034 #{ # data
18035 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18036 #}
18037 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18038 $CurClass = $2;
18039 }
18040 }
18041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018042 }
18043 close(PREPROC);
18044 foreach my $Constant (keys(%{$Constants{$Version}}))
18045 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018046 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18047 {
18048 delete($Constants{$Version}{$Constant});
18049 next;
18050 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018051 if(not $ExtraDump and ($Constant=~/_h\Z/i
18052 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018053 { # skip
18054 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018055 }
18056 else {
18057 delete($Constants{$Version}{$Constant}{"Access"});
18058 }
18059 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018060 if($Debug)
18061 {
18062 mkpath($DEBUG_PATH{$Version});
18063 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018065}
18066
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018067sub uncoverConstant($$)
18068{
18069 my ($LibVersion, $Constant) = @_;
18070 return "" if(not $LibVersion or not $Constant);
18071 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18072 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18073 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18074 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018075
18076 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018077 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018078 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18079 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018080 {
18081 push(@RecurConstant, $Constant);
18082 my $Uncovered = uncoverConstant($LibVersion, $Value);
18083 if($Uncovered ne "") {
18084 $Value = $Uncovered;
18085 }
18086 pop(@RecurConstant);
18087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018088
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018089 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018090 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018091 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18092 }
18093 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18094}
18095
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018096sub simpleConstant($$)
18097{
18098 my ($LibVersion, $Value) = @_;
18099 if($Value=~/\W/)
18100 {
18101 my $Value_Copy = $Value;
18102 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18103 {
18104 my $Word = $1;
18105 if($Value!~/$Word\s*\(/)
18106 {
18107 my $Val = uncoverConstant($LibVersion, $Word);
18108 if($Val ne "")
18109 {
18110 $Value=~s/\b$Word\b/$Val/g;
18111 }
18112 }
18113 }
18114 }
18115 return $Value;
18116}
18117
18118sub computeValue($)
18119{
18120 my $Value = $_[0];
18121
18122 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18123 return $1;
18124 }
18125
18126 if($Value=~/\A[\d\-\+()]+\Z/) {
18127 return eval($Value);
18128 }
18129
18130 return $Value;
18131}
18132
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018133my %IgnoreConstant = map {$_=>1} (
18134 "VERSION",
18135 "VERSIONCODE",
18136 "VERNUM",
18137 "VERS_INFO",
18138 "PATCHLEVEL",
18139 "INSTALLPREFIX",
18140 "VBUILD",
18141 "VPATCH",
18142 "VMINOR",
18143 "BUILD_STRING",
18144 "BUILD_TIME",
18145 "PACKAGE_STRING",
18146 "PRODUCTION",
18147 "CONFIGURE_COMMAND",
18148 "INSTALLDIR",
18149 "BINDIR",
18150 "CONFIG_FILE_PATH",
18151 "DATADIR",
18152 "EXTENSION_DIR",
18153 "INCLUDE_PATH",
18154 "LIBDIR",
18155 "LOCALSTATEDIR",
18156 "SBINDIR",
18157 "SYSCONFDIR",
18158 "RELEASE",
18159 "SOURCE_ID",
18160 "SUBMINOR",
18161 "MINOR",
18162 "MINNOR",
18163 "MINORVERSION",
18164 "MAJOR",
18165 "MAJORVERSION",
18166 "MICRO",
18167 "MICROVERSION",
18168 "BINARY_AGE",
18169 "INTERFACE_AGE",
18170 "CORE_ABI",
18171 "PATCH",
18172 "COPYRIGHT",
18173 "TIMESTAMP",
18174 "REVISION",
18175 "PACKAGE_TAG",
18176 "PACKAGEDATE",
18177 "NUMVERSION",
18178 "Release",
18179 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018180);
18181
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018182sub constantFilter($$$)
18183{
18184 my ($Name, $Value, $Level) = @_;
18185
18186 if($Level eq "Binary")
18187 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018188 if($Name=~/_t\Z/)
18189 { # __malloc_ptr_t
18190 return 1;
18191 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018192 foreach (keys(%IgnoreConstant))
18193 {
18194 if($Name=~/(\A|_)$_(_|\Z)/)
18195 { # version
18196 return 1;
18197 }
18198 if(/\A[A-Z].*[a-z]\Z/)
18199 {
18200 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18201 { # version
18202 return 1;
18203 }
18204 }
18205 }
18206 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18207 { # version
18208 return 1;
18209 }
18210 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18211 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18212 return 1;
18213 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018214
18215 if($Value=~/\A["'].*['"]/i)
18216 { # string
18217 return 0;
18218 }
18219
18220 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18221 { # static int gcry_pth_init
18222 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018223 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018224 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018225 return 1;
18226 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018227 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018228 { # foo(p)
18229 return 1;
18230 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018231 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018232 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018233 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018234 return 1;
18235 }
18236 }
18237
18238 return 0;
18239}
18240
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018241sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018242{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018243 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018244 foreach my $Constant (keys(%{$Constants{1}}))
18245 {
18246 if($SkipConstants{1}{$Constant})
18247 { # skipped by the user
18248 next;
18249 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018250
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018251 if(my $Header = $Constants{1}{$Constant}{"Header"})
18252 {
18253 if(not is_target_header($Header, 1)
18254 and not is_target_header($Header, 2))
18255 { # user-defined header
18256 next;
18257 }
18258 }
18259 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018260 next;
18261 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018262
18263 my $Old_Value = uncoverConstant(1, $Constant);
18264
18265 if(constantFilter($Constant, $Old_Value, $Level))
18266 { # separate binary and source problems
18267 next;
18268 }
18269
18270 if(not defined $Constants{2}{$Constant}{"Value"})
18271 { # removed
18272 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18273 "Target"=>$Constant,
18274 "Old_Value"=>$Old_Value );
18275 next;
18276 }
18277
18278 if($Constants{2}{$Constant}{"Value"} eq "")
18279 { # empty value
18280 # TODO: implement a rule
18281 next;
18282 }
18283
18284 my $New_Value = uncoverConstant(2, $Constant);
18285
18286 my $Old_Value_Pure = $Old_Value;
18287 my $New_Value_Pure = $New_Value;
18288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018289 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18290 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18291 $New_Value_Pure=~s/(\W)\s+/$1/g;
18292 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018293
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018294 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018296 if($New_Value_Pure ne $Old_Value_Pure)
18297 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018298 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18299 { # complex values
18300 next;
18301 }
18302 if(computeValue($Old_Value) eq computeValue($New_Value))
18303 { # expressions
18304 next;
18305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018306 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18307 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18308 next;
18309 }
18310 if($Old_Value eq "0" and $New_Value eq "NULL")
18311 { # 0 => NULL
18312 next;
18313 }
18314 if($Old_Value eq "NULL" and $New_Value eq "0")
18315 { # NULL => 0
18316 next;
18317 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018318 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018319 "Target"=>$Constant,
18320 "Old_Value"=>$Old_Value,
18321 "New_Value"=>$New_Value );
18322 }
18323 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018324
18325 foreach my $Constant (keys(%{$Constants{2}}))
18326 {
18327 if(not defined $Constants{1}{$Constant}{"Value"})
18328 {
18329 if($SkipConstants{2}{$Constant})
18330 { # skipped by the user
18331 next;
18332 }
18333
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018334 if(my $Header = $Constants{2}{$Constant}{"Header"})
18335 {
18336 if(not is_target_header($Header, 1)
18337 and not is_target_header($Header, 2))
18338 { # user-defined header
18339 next;
18340 }
18341 }
18342 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018343 next;
18344 }
18345
18346 my $New_Value = uncoverConstant(2, $Constant);
18347 if(not defined $New_Value or $New_Value eq "") {
18348 next;
18349 }
18350
18351 if(constantFilter($Constant, $New_Value, $Level))
18352 { # separate binary and source problems
18353 next;
18354 }
18355
18356 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18357 "Target"=>$Constant,
18358 "New_Value"=>$New_Value );
18359 }
18360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018361}
18362
18363sub convert_integer($)
18364{
18365 my $Value = $_[0];
18366 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018367 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018368 return hex($Value);
18369 }
18370 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018371 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018372 return oct($Value);
18373 }
18374 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018375 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018376 return oct($Value);
18377 }
18378 else {
18379 return $Value;
18380 }
18381}
18382
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018383sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018384{
18385 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018386 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018387 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018388 {
18389 if($LibVersion==1)
18390 {
18391 printMsg("WARNING", "checking headers only");
18392 $CheckHeadersOnly = 1;
18393 }
18394 else {
18395 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18396 }
18397 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018398
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018399 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018400 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018401 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018402
18403 if($CheckUndefined)
18404 {
18405 my %UndefinedLibs = ();
18406
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018407 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18408
18409 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018410 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018411 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018412 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018413 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018414 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018415 if($Symbol_Library{$LibVersion}{$Symbol}
18416 or $DepSymbol_Library{$LibVersion}{$Symbol})
18417 { # exported by target library
18418 next;
18419 }
18420 if(index($Symbol, '@')!=-1)
18421 { # exported default symbol version (@@)
18422 $Symbol=~s/\@/\@\@/;
18423 if($Symbol_Library{$LibVersion}{$Symbol}
18424 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18425 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018426 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018427 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018428 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18429 $UndefinedLibs{$Path} = 1;
18430 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018431 }
18432 }
18433 }
18434 if($ExtraInfo)
18435 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018436 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018437 {
18438 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018439 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018440 foreach (@Paths)
18441 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018442 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018443 my ($Dir, $Name) = separate_path($_);
18444
18445 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018446 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018447 }
18448
18449 $Name = parse_libname($Name, "name", $OStarget);
18450 $Name=~s/\Alib//;
18451
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018452 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018453 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018454
18455 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18456 {
18457 $LibString = " -L".esc($Dir).$LibString;
18458 }
18459
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018460 writeFile($ExtraInfo."/libs-string", $LibString);
18461 }
18462 }
18463 }
18464
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018465 if($ExtraInfo) {
18466 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18467 }
18468
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018469 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018470 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018471 if($#LibPaths!=-1)
18472 {
18473 if(not keys(%{$Symbol_Library{$LibVersion}}))
18474 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018475 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018476 printMsg("WARNING", "checking headers only");
18477 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018478 }
18479 }
18480 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018481
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018482 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018483 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018484}
18485
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018486my %Prefix_Lib_Map=(
18487 # symbols for autodetecting library dependencies (by prefix)
18488 "pthread_" => ["libpthread"],
18489 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18490 "cairo_" => ["libcairo"],
18491 "gtk_" => ["libgtk-x11-2.0"],
18492 "atk_" => ["libatk-1.0"],
18493 "gdk_" => ["libgdk-x11-2.0"],
18494 "gl" => ["libGL"],
18495 "glu" => ["libGLU"],
18496 "popt" => ["libpopt"],
18497 "Py" => ["libpython"],
18498 "jpeg_" => ["libjpeg"],
18499 "BZ2_" => ["libbz2"],
18500 "Fc" => ["libfontconfig"],
18501 "Xft" => ["libXft"],
18502 "SSL_" => ["libssl"],
18503 "sem_" => ["libpthread"],
18504 "snd_" => ["libasound"],
18505 "art_" => ["libart_lgpl_2"],
18506 "dbus_g" => ["libdbus-glib-1"],
18507 "GOMP_" => ["libgomp"],
18508 "omp_" => ["libgomp"],
18509 "cms" => ["liblcms"]
18510);
18511
18512my %Pattern_Lib_Map=(
18513 "SL[a-z]" => ["libslang"]
18514);
18515
18516my %Symbol_Lib_Map=(
18517 # symbols for autodetecting library dependencies (by name)
18518 "pow" => "libm",
18519 "fmod" => "libm",
18520 "sin" => "libm",
18521 "floor" => "libm",
18522 "cos" => "libm",
18523 "dlopen" => "libdl",
18524 "deflate" => "libz",
18525 "inflate" => "libz",
18526 "move_panel" => "libpanel",
18527 "XOpenDisplay" => "libX11",
18528 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018529 "clock_gettime" => "librt",
18530 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018531);
18532
18533sub find_SymbolLibs($$)
18534{
18535 my ($LibVersion, $Symbol) = @_;
18536
18537 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18538 { # debug symbols
18539 return ();
18540 }
18541
18542 my %Paths = ();
18543
18544 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18545 {
18546 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18547 $Paths{$Path} = 1;
18548 }
18549 }
18550
18551 if(my $SymbolPrefix = getPrefix($Symbol))
18552 {
18553 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18554 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18555 }
18556
18557 if(not keys(%Paths))
18558 {
18559 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18560 {
18561 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18562 {
18563 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18564 $Paths{$Path} = 1;
18565 }
18566 }
18567 }
18568 }
18569
18570 if(not keys(%Paths))
18571 {
18572 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18573 {
18574 if($Symbol=~/\A$Prefix/)
18575 {
18576 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18577 {
18578 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18579 $Paths{$Path} = 1;
18580 }
18581 }
18582 }
18583 }
18584 }
18585
18586 if(not keys(%Paths))
18587 {
18588 if($SymbolPrefix)
18589 { # try to find a library by symbol prefix
18590 if($SymbolPrefix eq "inotify" and
18591 index($Symbol, "\@GLIBC")!=-1)
18592 {
18593 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18594 $Paths{$Path} = 1;
18595 }
18596 }
18597 else
18598 {
18599 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18600 $Paths{$Path} = 1;
18601 }
18602 }
18603 }
18604 }
18605
18606 if(my @Paths = keys(%Paths)) {
18607 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18608 }
18609 }
18610 return keys(%Paths);
18611}
18612
18613sub get_LibPath_Prefix($$)
18614{
18615 my ($LibVersion, $Prefix) = @_;
18616
18617 $Prefix = lc($Prefix);
18618 $Prefix=~s/[_]+\Z//g;
18619
18620 foreach ("-2", "2", "-1", "1", "")
18621 { # libgnome-2.so
18622 # libxml2.so
18623 # libdbus-1.so
18624 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18625 return $Path;
18626 }
18627 }
18628 return "";
18629}
18630
18631sub getPrefix($)
18632{
18633 my $Str = $_[0];
18634 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18635 { # XmuValidArea: Xmu
18636 return $1;
18637 }
18638 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18639 { # snfReadFont: snf
18640 return $1;
18641 }
18642 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18643 { # XRRTimes: XRR
18644 return $1;
18645 }
18646 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18647 { # H5HF_delete: H5
18648 return $1;
18649 }
18650 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18651 { # alarm_event_add: alarm_
18652 return $1;
18653 }
18654 elsif($Str=~/\A(([a-z])\2{1,})/i)
18655 { # ffopen
18656 return $1;
18657 }
18658 return "";
18659}
18660
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018661sub getSymbolSize($$)
18662{ # size from the shared library
18663 my ($Symbol, $LibVersion) = @_;
18664 return 0 if(not $Symbol);
18665 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18666 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18667 {
18668 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18669 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18670 {
18671 if($Size<0) {
18672 return -$Size;
18673 }
18674 }
18675 }
18676 return 0;
18677}
18678
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018679sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018680{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18681 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018682 my ($Name, $Type) = @_;
18683
18684 # single
18685 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018686 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018687 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018688 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018689 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018690
18691 # double
18692 if($Name=~/$DEFAULT_STD_PARMS/)
18693 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018694 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018695 {
18696 my ($ShortName, $FuncParams) = split_Signature($Name);
18697
18698 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18699 {
18700 if(index($FParam, "<")!=-1)
18701 {
18702 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18703 my $FParam_N = canonifyName($FParam, "T");
18704 if($FParam_N ne $FParam) {
18705 $Name=~s/\Q$FParam\E/$FParam_N/g;
18706 }
18707 }
18708 }
18709 }
18710 elsif($Type eq "T")
18711 {
18712 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18713
18714 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018715 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018716 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018717 my $FParam = $TParams[0];
18718 foreach my $Pos (1 .. $#TParams)
18719 {
18720 my $TParam = $TParams[$Pos];
18721 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18722 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18723 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018724 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018725 }
18726 }
18727 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018728 if($Type eq "S") {
18729 return formatName($Name, "S");
18730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018731 return $Name;
18732}
18733
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018734sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018735{
18736 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018737 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018738 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018739 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018740 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018741 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018742 next if($tr_name{$Symbol});
18743 $Symbol=~s/[\@\$]+(.*)\Z//;
18744 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018745 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018746 elsif(index($Symbol, "?")==0)
18747 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018748 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018749 }
18750 else
18751 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018752 $tr_name{$Symbol} = $Symbol;
18753 $mangled_name_gcc{$Symbol} = $Symbol;
18754 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018755 }
18756 }
18757 if($#MnglNames1 > -1)
18758 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018759 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018760 foreach my $MnglName (@MnglNames1)
18761 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018762 if(my $Unmangled = pop(@UnmangledNames))
18763 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018764 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018765 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18766 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18767 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018768 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018769 and $tr_name{$MnglName}=~/vtable for (.+)/)
18770 { # bind class name and v-table symbol
18771 my $ClassName = $1;
18772 $ClassVTable{$ClassName} = $MnglName;
18773 $VTableClass{$MnglName} = $ClassName;
18774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018775 }
18776 }
18777 }
18778 if($#MnglNames2 > -1)
18779 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018780 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018781 foreach my $MnglName (@MnglNames2)
18782 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018783 if(my $Unmangled = pop(@UnmangledNames))
18784 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018785 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018786 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018788 }
18789 }
18790 return \%tr_name;
18791}
18792
18793sub link_symbol($$$)
18794{
18795 my ($Symbol, $RunWith, $Deps) = @_;
18796 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18797 return 1;
18798 }
18799 if($Deps eq "+Deps")
18800 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018801 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802 return 1;
18803 }
18804 }
18805 return 0;
18806}
18807
18808sub link_symbol_internal($$$)
18809{
18810 my ($Symbol, $RunWith, $Where) = @_;
18811 return 0 if(not $Where or not $Symbol);
18812 if($Where->{$RunWith}{$Symbol})
18813 { # the exact match by symbol name
18814 return 1;
18815 }
18816 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18817 { # indirect symbol version, i.e.
18818 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018819 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018820 if($Where->{$RunWith}{$VSym}) {
18821 return 1;
18822 }
18823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018824 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018825 if($Sym and $Ver)
18826 { # search for the symbol with the same version
18827 # or without version
18828 if($Where->{$RunWith}{$Sym})
18829 { # old: foo@v|foo@@v
18830 # new: foo
18831 return 1;
18832 }
18833 if($Where->{$RunWith}{$Sym."\@".$Ver})
18834 { # old: foo|foo@@v
18835 # new: foo@v
18836 return 1;
18837 }
18838 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18839 { # old: foo|foo@v
18840 # new: foo@@v
18841 return 1;
18842 }
18843 }
18844 return 0;
18845}
18846
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018847sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018848{
18849 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018850 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018852 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018854 my $NM = get_CmdPath("nm");
18855 if(not $NM) {
18856 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018857 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018858 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018859 while(<APP>)
18860 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018861 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018862 push(@Imported, $1);
18863 }
18864 }
18865 close(APP);
18866 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018867 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018868 {
18869 my $DumpBinCmd = get_CmdPath("dumpbin");
18870 if(not $DumpBinCmd) {
18871 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18872 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018873 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018874 while(<APP>)
18875 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18877 push(@Imported, $1);
18878 }
18879 }
18880 close(APP);
18881 }
18882 else
18883 {
18884 my $ReadelfCmd = get_CmdPath("readelf");
18885 if(not $ReadelfCmd) {
18886 exitStatus("Not_Found", "can't find \"readelf\"");
18887 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018888 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018889 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018890 while(<APP>)
18891 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018892 if(defined $symtab)
18893 { # do nothing with symtab
18894 if(index($_, "'.dynsym'")!=-1)
18895 { # dynamic table
18896 $symtab = undef;
18897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018898 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018899 elsif(index($_, "'.symtab'")!=-1)
18900 { # symbol table
18901 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018902 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018903 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018904 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018905 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18906 if($Ndx eq "UND")
18907 { # only imported symbols
18908 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018909 }
18910 }
18911 }
18912 close(APP);
18913 }
18914 return @Imported;
18915}
18916
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018917my %ELF_BIND = map {$_=>1} (
18918 "WEAK",
18919 "GLOBAL"
18920);
18921
18922my %ELF_TYPE = map {$_=>1} (
18923 "FUNC",
18924 "IFUNC",
18925 "OBJECT",
18926 "COMMON"
18927);
18928
18929my %ELF_VIS = map {$_=>1} (
18930 "DEFAULT",
18931 "PROTECTED"
18932);
18933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018934sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018935{ # read the line of 'readelf' output corresponding to the symbol
18936 my @Info = split(/\s+/, $_[0]);
18937 # Num: Value Size Type Bind Vis Ndx Name
18938 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018939 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018940 shift(@Info); # spaces
18941 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018942
18943 if($#Info==7)
18944 { # UND SYMBOL (N)
18945 if($Info[7]=~/\(\d+\)/) {
18946 pop(@Info);
18947 }
18948 }
18949
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018950 if($#Info!=6)
18951 { # other lines
18952 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018953 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018954 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018955 return () if(not defined $ELF_BIND{$Info[3]});
18956 return () if(not defined $ELF_VIS{$Info[4]});
18957 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18958 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18959 return ();
18960 }
18961 if($OStarget eq "symbian")
18962 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18963 if(index($Info[6], "_._.absent_export_")!=-1)
18964 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18965 return ();
18966 }
18967 $Info[6]=~s/\@.+//g; # remove version
18968 }
18969 if(index($Info[2], "0x") == 0)
18970 { # size == 0x3d158
18971 $Info[2] = hex($Info[2]);
18972 }
18973 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018974}
18975
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018976sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018977{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018978 my ($LibVersion, $Name) = @_;
18979 return "" if(not $LibVersion or not $Name);
18980 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18981 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018982 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18984}
18985
18986sub get_LibPath_I($$)
18987{
18988 my ($LibVersion, $Name) = @_;
18989 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018990 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018991 if(-f $Name)
18992 { # absolute path
18993 return $Name;
18994 }
18995 else
18996 { # broken
18997 return "";
18998 }
18999 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019000 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019002 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019003 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019004 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019005 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019006 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019007 }
19008 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19009 { # ldconfig default paths
19010 return $DefaultPath;
19011 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019012 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019013 { # search in default linker directories
19014 # and then in all system paths
19015 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019016 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019017 }
19018 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019019 if(not defined $Cache{"checkSystemFiles"}) {
19020 checkSystemFiles();
19021 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019022 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19023 return $AllObjects[0];
19024 }
19025 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19026 {
19027 if($ShortName ne $Name)
19028 { # FIXME: check this case
19029 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19030 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019031 }
19032 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019033 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019034 # can't find
19035 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019036}
19037
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019038sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019039{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019040 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19041 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019042
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019043 my $Real_Path = realpath_F($Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019044
19045 if(not $Real_Path)
19046 { # broken link
19047 return ();
19048 }
19049
19050 my $Lib_Name = get_filename($Real_Path);
19051
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019052 if($ExtraInfo)
19053 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019054 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019055 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019056 }
19057
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019058 if($IsNeededLib)
19059 {
19060 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19061 return ();
19062 }
19063 }
19064 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019065 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019067 push(@RecurLib, $Lib_Name);
19068 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019069 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19070
19071 if(not $IsNeededLib)
19072 { # special cases: libstdc++ and libc
19073 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19074 {
19075 if($ShortName eq "libstdc++")
19076 { # libstdc++.so.6
19077 $STDCXX_TESTING = 1;
19078 }
19079 elsif($ShortName eq "libc")
19080 { # libc-2.11.3.so
19081 $GLIBC_TESTING = 1;
19082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019083 }
19084 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019085 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019086 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019087 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019088 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019089 mkpath(get_dirname($DebugPath));
19090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019091 if($OStarget eq "macos")
19092 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019093 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019094 if(not $NM) {
19095 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019096 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019097 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019098 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019099 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019100 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019101 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019102 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019103 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019104 else
19105 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019106 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019108 while(<LIB>)
19109 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019110 if($CheckUndefined)
19111 {
19112 if(not $IsNeededLib)
19113 {
19114 if(/ U _([\w\$]+)\s*\Z/)
19115 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019116 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019117 next;
19118 }
19119 }
19120 }
19121
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019122 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019123 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019124 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019125 if($IsNeededLib)
19126 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019127 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019128 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019129 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19130 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019132 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019133 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019135 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19136 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019137 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19138 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019139 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019140 setLanguage($LibVersion, "C++");
19141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019143 }
19144 }
19145 }
19146 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019147
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019148 if($Deps)
19149 {
19150 if($LIB_TYPE eq "dynamic")
19151 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019152
19153 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019154 if(not $OtoolCmd) {
19155 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019156 }
19157
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019158 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19159 while(<LIB>)
19160 {
19161 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19162 and $1 ne $Lib_Path) {
19163 $NeededLib{$1} = 1;
19164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019166 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168 }
19169 }
19170 elsif($OStarget eq "windows")
19171 { # Windows *.dll, *.lib
19172 my $DumpBinCmd = get_CmdPath("dumpbin");
19173 if(not $DumpBinCmd) {
19174 exitStatus("Not_Found", "can't find \"dumpbin\"");
19175 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019176 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019177 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019178 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019179 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019180 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019181 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019182 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019183 else
19184 { # write to pipe
19185 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019187 while(<LIB>)
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019188 {
19189 my $realname = undef;
19190 if($LIB_TYPE eq "dynamic")
19191 {
19192 # 1197 4AC 0000A620 SetThreadStackGuarantee
19193 # 1198 4AD SetThreadToken (forwarded to ...)
19194 # 3368 _o2i_ECPublicKey
19195 # 1 0 00005B30 ??0?N = ... (with pdb)
19196 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
19197 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19198 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
19199 { # dynamic, static and forwarded symbols
19200 $realname = $1;
19201 }
19202 }
19203 else
19204 { # static
19205 if(/\A\s{10,}\d*\s+([\w\?\@]+)\s*\Z/i)
19206 {
19207 # 16 IID_ISecurityInformation
19208 $realname = $1;
19209 }
19210 }
19211
19212 if($realname)
19213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019214 if($IsNeededLib)
19215 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019216 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019217 {
19218 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19219 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019222 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019223 {
19224 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19225 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019226 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19227 {
19228 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19229 setLanguage($LibVersion, "C++");
19230 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019231 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 }
19233 }
19234 }
19235 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019236
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019237 if($Deps)
19238 {
19239 if($LIB_TYPE eq "dynamic")
19240 { # dependencies
19241 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19242 while(<LIB>)
19243 {
19244 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19245 and $1 ne $Lib_Path) {
19246 $NeededLib{path_format($1, $OSgroup)} = 1;
19247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019249 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 }
19252 }
19253 else
19254 { # Unix; *.so, *.a
19255 # Symbian: *.dso, *.lib
19256 my $ReadelfCmd = get_CmdPath("readelf");
19257 if(not $ReadelfCmd) {
19258 exitStatus("Not_Found", "can't find \"readelf\"");
19259 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019260 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019261 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019262 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019263 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019264 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019265 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019266 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019267 else
19268 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019269 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019270 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019271 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019272 while(<LIB>)
19273 {
19274 if($LIB_TYPE eq "dynamic")
19275 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019276 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019277 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019278 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019279 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019280 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019281 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019282 # do nothing with symtab
19283 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019284 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019285 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019286 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019287 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019288 next;
19289 }
19290 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019291 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019293 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019294 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019295 if($CheckUndefined)
19296 {
19297 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019298 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019299 }
19300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019301 next;
19302 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019303 if($Bind eq "WEAK")
19304 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019305 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019306 if($Weak eq "-Weak")
19307 { # skip WEAK symbols
19308 next;
19309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019310 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019311 my $Short = $Symbol;
19312 $Short=~s/\@.+//g;
19313 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019314 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019315 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19316 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019317 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019318 if($IsNeededLib)
19319 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019320 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019321 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019322 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19323 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019326 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019327 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019328 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19329 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19330 if($Vers)
19331 {
19332 if($LIB_EXT eq "so")
19333 { # value
19334 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19335 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019337 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019338 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19339 {
19340 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19341 setLanguage($LibVersion, "C++");
19342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019344 }
19345 }
19346 }
19347 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019348
19349 if($Deps and $LIB_TYPE eq "dynamic")
19350 { # dynamic library specifics
19351 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19352 open(LIB, $Cmd." |");
19353
19354 while(<LIB>)
19355 {
19356 if(/NEEDED.+\[([^\[\]]+)\]/)
19357 { # dependencies:
19358 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19359 $NeededLib{$1} = 1;
19360 }
19361 }
19362
19363 close(LIB);
19364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019365 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019366 if($Vers)
19367 {
19368 if(not $IsNeededLib and $LIB_EXT eq "so")
19369 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019370 my %Found = ();
19371
19372 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019373 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019374 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019375 next if(index($Symbol,"\@")==-1);
19376 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019377 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019378 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019379 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019380 if($Symbol_SameValue ne $Symbol
19381 and index($Symbol_SameValue,"\@")==-1)
19382 {
19383 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019384 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019385 last;
19386 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019387 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019388 }
19389 }
19390
19391 # default
19392 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19393 {
19394 next if(defined $Found{$Symbol});
19395 next if(index($Symbol,"\@\@")==-1);
19396
19397 if($Symbol=~/\A([^\@]*)\@\@/
19398 and not $SymVer{$LibVersion}{$1})
19399 {
19400 $SymVer{$LibVersion}{$1} = $Symbol;
19401 $Found{$Symbol} = 1;
19402 }
19403 }
19404
19405 # non-default
19406 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19407 {
19408 next if(defined $Found{$Symbol});
19409 next if(index($Symbol,"\@")==-1);
19410
19411 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19412 and not $SymVer{$LibVersion}{$1})
19413 {
19414 $SymVer{$LibVersion}{$1} = $Symbol;
19415 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019416 }
19417 }
19418 }
19419 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019420 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019421 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019422 foreach my $DyLib (sort keys(%NeededLib))
19423 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019424 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19425
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019426 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19427 {
19428 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19429 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19430 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 }
19433 }
19434 pop(@RecurLib);
19435 return $Library_Symbol{$LibVersion};
19436}
19437
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019438sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019439{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019440 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019441 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 return keys(%Prefixes);
19443}
19444
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019445sub get_prefixes_I($$)
19446{
19447 foreach my $P (@{$_[0]})
19448 {
19449 my @Parts = reverse(split(/[\/\\]+/, $P));
19450 my $Name = $Parts[0];
19451 foreach (1 .. $#Parts)
19452 {
19453 $_[1]->{$Name}{$P} = 1;
19454 last if($_>4 or $Parts[$_] eq "include");
19455 $Name = $Parts[$_].$SLASH.$Name;
19456 }
19457 }
19458}
19459
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019460sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019461{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019462 $Cache{"checkSystemFiles"} = 1;
19463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019464 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019465
19466 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019467 {
19468 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019469
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019470 my @Files = cmd_find($DevelPath,"f");
19471 foreach my $Link (cmd_find($DevelPath,"l"))
19472 { # add symbolic links
19473 if(-f $Link) {
19474 push(@Files, $Link);
19475 }
19476 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019477
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019478 # search for headers in /usr/lib
19479 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19480 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19481 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019482
19483 # search for libraries in /usr/lib (including symbolic links)
19484 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19485 foreach my $Path (@Libs)
19486 {
19487 my $N = get_filename($Path);
19488 $SystemObjects{$N}{$Path} = 1;
19489 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019490 }
19491 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019492
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019493 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019494 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019495 next if(not -d $DevelPath);
19496 # search for all header files in the /usr/include
19497 # with or without extension (ncurses.h, QtCore, ...)
19498 push(@SysHeaders, cmd_find($DevelPath,"f"));
19499 foreach my $Link (cmd_find($DevelPath,"l"))
19500 { # add symbolic links
19501 if(-f $Link) {
19502 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019504 }
19505 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019506 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019507}
19508
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019509sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019510{
19511 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019512 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019513 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19514 {
19515 if(not -e $Dest) {
19516 exitStatus("Access_Error", "can't access \'$Dest\'");
19517 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019518 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019519 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19520 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019521 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019522 }
19523 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019524 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019525}
19526
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019527sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019528{
19529 my ($Path, $LibVersion) = @_;
19530 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019531 my $Name = get_filename($Path);
19532 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019533 return 1;
19534 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019535 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019536 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19537 return 1;
19538 }
19539 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19540 {
19541 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19542 return 1;
19543 }
19544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019545 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019546 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019547 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019548 return 1;
19549 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019550 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019551 return 1;
19552 }
19553 }
19554 return 0;
19555}
19556
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019557sub specificHeader($$)
19558{
19559 my ($Header, $Spec) = @_;
19560 my $Name = get_filename($Header);
19561
19562 if($Spec eq "windows")
19563 {# MS Windows
19564 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19565 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19566 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19567 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19568 my @Dirs = (
19569 "win32",
19570 "win64",
19571 "win",
19572 "windows",
19573 "msvcrt"
19574 ); # /gsf-win32/
19575 if(my $DIRs = join("|", @Dirs)) {
19576 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19577 }
19578 }
19579 elsif($Spec eq "macos")
19580 { # Mac OS
19581 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19582 }
19583
19584 return 0;
19585}
19586
19587sub skipAlienHeader($)
19588{
19589 my $Path = $_[0];
19590 my $Name = get_filename($Path);
19591 my $Dir = get_dirname($Path);
19592
19593 if($Tolerance=~/2/)
19594 { # 2 - skip internal headers
19595 my @Terms = (
19596 "p",
19597 "priv",
19598 "int",
19599 "impl",
19600 "implementation",
19601 "internal",
19602 "private",
19603 "old",
19604 "compat",
19605 "debug",
19606 "test",
19607 "gen"
19608 );
19609
19610 my @Dirs = (
19611 "private",
19612 "priv",
19613 "port",
19614 "impl",
19615 "internal",
19616 "detail",
19617 "details",
19618 "old",
19619 "compat",
19620 "debug",
19621 "config",
19622 "compiler",
19623 "platform",
19624 "test"
19625 );
19626
19627 if(my $TERMs = join("|", @Terms)) {
19628 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19629 }
19630 if(my $DIRs = join("|", @Dirs)) {
19631 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19632 }
19633
19634 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19635 }
19636
19637 if($Tolerance=~/1/)
19638 { # 1 - skip non-Linux headers
19639 if($OSgroup ne "windows")
19640 {
19641 if(specificHeader($Path, "windows")) {
19642 return 1;
19643 }
19644 }
19645 if($OSgroup ne "macos")
19646 {
19647 if(specificHeader($Path, "macos")) {
19648 return 1;
19649 }
19650 }
19651 }
19652
19653 # valid
19654 return 0;
19655}
19656
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019657sub skipHeader($$)
19658{
19659 my ($Path, $LibVersion) = @_;
19660 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019661 if(defined $Cache{"skipHeader"}{$Path}) {
19662 return $Cache{"skipHeader"}{$Path};
19663 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019664 if(defined $Tolerance and $Tolerance=~/1|2/)
19665 { # --tolerant
19666 if(skipAlienHeader($Path)) {
19667 return ($Cache{"skipHeader"}{$Path} = 1);
19668 }
19669 }
19670 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19671 return 0;
19672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019673 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19674}
19675
19676sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019677{ # returns:
19678 # 1 - if header should NOT be included and checked
19679 # 2 - if header should NOT be included, but should be checked
19680 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019681 my $Name = get_filename($Path);
19682 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019683 return $Kind;
19684 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019685 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19686 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019687 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019688 if(index($Path, $D)!=-1)
19689 {
19690 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19691 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019693 }
19694 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019695 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19696 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019697 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019698 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19699 {
19700 if($Name=~/$P/) {
19701 return $Kind;
19702 }
19703 if($P=~/[\/\\]/ and $Path=~/$P/) {
19704 return $Kind;
19705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019706 }
19707 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019708
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019709 return 0;
19710}
19711
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019712sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019713{
19714 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019715 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019716 { # system directory
19717 return;
19718 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019719 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019720 { # already registered
19721 return;
19722 }
19723 foreach my $Path (find_libs($Dir,"",1))
19724 {
19725 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019726 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019727 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019728 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019729 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19730}
19731
19732sub registerObject($$)
19733{
19734 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019735
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019736 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019737 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019738 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019739 {
19740 if(my $SONAME = getSONAME($Path)) {
19741 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019743 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019744 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19745 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019746 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019747
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019748 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019749 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019750 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019751 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019752 if($ObjArch ne getArch_GCC($LibVersion))
19753 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19754 $CheckedArch{$LibVersion} = 1;
19755 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 +040019756 }
19757 }
19758 }
19759}
19760
19761sub getArch_Object($)
19762{
19763 my $Path = $_[0];
19764
19765 my %MachineType = (
19766 "14C" => "x86",
19767 "8664" => "x86_64",
19768 "1C0" => "arm",
19769 "200" => "ia64"
19770 );
19771
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019772 my %ArchName = (
19773 "s390:31-bit" => "s390",
19774 "s390:64-bit" => "s390x",
19775 "powerpc:common" => "ppc32",
19776 "powerpc:common64" => "ppc64",
19777 "i386:x86-64" => "x86_64",
19778 "mips:3000" => "mips",
19779 "sparc:v8plus" => "sparcv9"
19780 );
19781
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019782 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019783 {
19784 my $DumpbinCmd = get_CmdPath("dumpbin");
19785 if(not $DumpbinCmd) {
19786 exitStatus("Not_Found", "can't find \"dumpbin\"");
19787 }
19788
19789 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19790 my $Out = `$Cmd`;
19791
19792 if($Out=~/(\w+)\smachine/)
19793 {
19794 if(my $Type = $MachineType{uc($1)})
19795 {
19796 return $Type;
19797 }
19798 }
19799 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019800 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019801 {
19802 my $ObjdumpCmd = get_CmdPath("objdump");
19803 if(not $ObjdumpCmd) {
19804 exitStatus("Not_Found", "can't find \"objdump\"");
19805 }
19806
19807 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019808
19809 if($OSgroup eq "windows") {
19810 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19811 }
19812 else {
19813 $Cmd = "LANG=$LOCALE ".$Cmd;
19814 }
19815 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019816
19817 if($Out=~/architecture:\s+([\w\-\:]+)/)
19818 {
19819 my $Arch = $1;
19820 if($Arch=~s/\:(.+)//)
19821 {
19822 my $Suffix = $1;
19823
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019824 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019825 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019826 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019827 }
19828 }
19829
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019830 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019831 $Arch = "x86";
19832 }
19833
19834 if($Arch eq "x86-64") {
19835 $Arch = "x86_64";
19836 }
19837
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019838 if($Arch eq "ia64-elf64") {
19839 $Arch = "ia64";
19840 }
19841
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019842 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019843 }
19844 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019845 elsif($OStarget=~/macos/)
19846 {
19847 my $OtoolCmd = get_CmdPath("otool");
19848 if(not $OtoolCmd) {
19849 exitStatus("Not_Found", "can't find \"otool\"");
19850 }
19851
19852 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19853 my $Out = qx/$Cmd/;
19854
19855 if($Out=~/X86_64/i) {
19856 return "x86_64";
19857 }
19858 elsif($Out=~/X86/i) {
19859 return "x86";
19860 }
19861 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019862 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019863 {
19864 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019865 # TODO
19866 }
19867
19868 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019869}
19870
19871sub getSONAME($)
19872{
19873 my $Path = $_[0];
19874 return if(not $Path);
19875 if(defined $Cache{"getSONAME"}{$Path}) {
19876 return $Cache{"getSONAME"}{$Path};
19877 }
19878 my $ObjdumpCmd = get_CmdPath("objdump");
19879 if(not $ObjdumpCmd) {
19880 exitStatus("Not_Found", "can't find \"objdump\"");
19881 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019882 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019883 if($OSgroup eq "windows") {
19884 $SonameCmd .= " | find \"SONAME\"";
19885 }
19886 else {
19887 $SonameCmd .= " | grep SONAME";
19888 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019889 if(my $SonameInfo = `$SonameCmd`)
19890 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019891 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19892 return ($Cache{"getSONAME"}{$Path} = $1);
19893 }
19894 }
19895 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019896}
19897
19898sub getSOPaths_Dest($$)
19899{
19900 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019901 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019902 return ();
19903 }
19904 if(-f $Dest)
19905 {
19906 if(not parse_libname($Dest, "name", $OStarget)) {
19907 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19908 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019909 registerObject($Dest, $LibVersion);
19910 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019911 return ($Dest);
19912 }
19913 elsif(-d $Dest)
19914 {
19915 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019916 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019917 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019918 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19919 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019920 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019921 { # all files and symlinks that match the name of a library
19922 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19923 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019924 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019925 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019926 }
19927 }
19928 }
19929 else
19930 { # search for all files and symlinks
19931 foreach my $Path (find_libs($Dest,"",""))
19932 {
19933 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019934 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019935 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019936 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019937 }
19938 if($OSgroup eq "macos")
19939 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019940 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019941 {
19942 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019943 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019944 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019945 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19946 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019947 registerObject($Path, $LibVersion);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019948 $Libs{realpath_F($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019949 }
19950 }
19951 }
19952 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019953 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019954 }
19955 else {
19956 return ();
19957 }
19958}
19959
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030019960sub realpath_F($)
19961{
19962 my $Path = $_[0];
19963 return path_format(realpath($Path), $OSgroup);
19964}
19965
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019966sub isCyclical($$)
19967{
19968 my ($Stack, $Value) = @_;
19969 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019970}
19971
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019972sub getGCC_Opts($)
19973{ # to use in module
19974 my $LibVersion = $_[0];
19975
19976 my @Opts = ();
19977
19978 if($CompilerOptions{$LibVersion})
19979 { # user-defined options
19980 push(@Opts, $CompilerOptions{$LibVersion});
19981 }
19982 if($GccOptions)
19983 { # additional
19984 push(@Opts, $GccOptions);
19985 }
19986
19987 if(@Opts) {
19988 return join(" ", @Opts);
19989 }
19990
19991 return undef;
19992}
19993
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019994sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019995{
19996 my $LibVersion = $_[0];
19997
19998 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19999 return $Cache{"getArch_GCC"}{$LibVersion};
20000 }
20001
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020002 if(not $GCC_PATH) {
20003 return undef;
20004 }
20005
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020006 my $Arch = undef;
20007
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030020008 if(my $Target = get_dumpmachine($GCC_PATH))
20009 {
20010 if($Target=~/x86_64/) {
20011 $Arch = "x86_64";
20012 }
20013 elsif($Target=~/i[3-6]86/) {
20014 $Arch = "x86";
20015 }
20016 elsif($Target=~/\Aarm/i) {
20017 $Arch = "arm";
20018 }
20019 }
20020
20021 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020022 {
20023 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
20024
20025 my $Cmd = $GCC_PATH." test.c -o test";
20026 if(my $Opts = getGCC_Opts($LibVersion))
20027 { # user-defined options
20028 $Cmd .= " ".$Opts;
20029 }
20030
20031 chdir($TMP_DIR);
20032 system($Cmd);
20033 chdir($ORIG_DIR);
20034
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020035 my $EX = join_P($TMP_DIR, "test");
20036
20037 if($OSgroup eq "windows") {
20038 $EX = join_P($TMP_DIR, "test.exe");
20039 }
20040
20041 $Arch = getArch_Object($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020042
20043 unlink("$TMP_DIR/test.c");
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020044 unlink($EX);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020045 }
20046
20047 if(not $Arch) {
20048 exitStatus("Error", "can't check ARCH type");
20049 }
20050
20051 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
20052}
20053
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020054sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020055{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020056 my $LibVersion = $_[0];
20057
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020058 my $Size = undef;
20059
20060 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020061 if(my $Arch = getArch($LibVersion))
20062 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020063 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020064 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020066 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20067 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020068 }
20069 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020070
20071 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020072 {
20073 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020074
20075 my $Cmd = $GCC_PATH." -E -dD empty.h";
20076 if(my $Opts = getGCC_Opts($LibVersion))
20077 { # user-defined options
20078 $Cmd .= " ".$Opts;
20079 }
20080
20081 chdir($TMP_DIR);
20082 my $Defines = `$Cmd`;
20083 chdir($ORIG_DIR);
20084
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020085 unlink("$TMP_DIR/empty.h");
20086
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020087 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20088 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020089 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020090 }
20091 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20092 { # GCC 3
20093 my $PTRDIFF = $1;
20094 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020095 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020096 }
20097 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020098 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020099 }
20100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020101 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020102
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020103 if(not $Size) {
20104 exitStatus("Error", "can't check WORD size");
20105 }
20106
20107 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020108}
20109
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020110sub getWordSize($)
20111{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020112 return $WORD_SIZE{$_[0]};
20113}
20114
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020115sub majorVersion($)
20116{
20117 my $V = $_[0];
20118 return 0 if(not $V);
20119 my @VParts = split(/\./, $V);
20120 return $VParts[0];
20121}
20122
20123sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020124{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020125 my ($V1, $V2) = @_;
20126 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020127 my @V1Parts = split(/\./, $V1);
20128 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020129 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20130 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020131 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20132 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20133 }
20134 return -1 if($#V1Parts < $#V2Parts);
20135 return 1 if($#V1Parts > $#V2Parts);
20136 return 0;
20137}
20138
20139sub read_ABI_Dump($$)
20140{
20141 my ($LibVersion, $Path) = @_;
20142 return if(not $LibVersion or not -e $Path);
20143 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020144 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020145 { # input *.abi
20146 $FilePath = $Path;
20147 }
20148 else
20149 { # input *.abi.tar.gz
20150 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020151 if(not isDump_U($FilePath)) {
20152 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020154 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020155
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020156 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020157
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020158 my $Line = readLineNum($FilePath, 0);
20159 if($Line=~/xml/)
20160 { # XML format
20161 loadModule("XmlDump");
20162 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020163 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020164 else
20165 { # Perl Data::Dumper format (default)
20166 open(DUMP, $FilePath);
20167 local $/ = undef;
20168 my $Content = <DUMP>;
20169 close(DUMP);
20170
20171 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20172 { # remove temp file
20173 unlink($FilePath);
20174 }
20175 if($Content!~/};\s*\Z/) {
20176 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20177 }
20178 $ABI = eval($Content);
20179 if(not $ABI) {
20180 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020182 }
20183 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020184 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020185 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020186 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020187 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020188 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020189 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020190 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020191 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020192
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020193 if($ABI->{"PublicABI"}) {
20194 $UsedDump{$LibVersion}{"Public"} = 1;
20195 }
20196
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020197 if($ABI->{"ABI_DUMP_VERSION"})
20198 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020199 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020200 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020201 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020202 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020203 }
20204 else
20205 { # support for old ABI dumps
20206 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020207 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020208 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020209 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020210 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020211
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020212 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020213 {
20214 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 +040020215 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020216
20217 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20218 { # DWARF ABI Dump
20219 $UseConv_Real{$LibVersion}{"P"} = 1;
20220 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20221
20222 $UsedDump{$LibVersion}{"DWARF"} = 1;
20223
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020224 if(not $TargetComponent_Opt)
20225 {
20226 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20227 $TargetComponent = "module";
20228 }
20229 else {
20230 $TargetComponent = "object";
20231 }
20232 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020233 }
20234
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020235 if(not checkDump($LibVersion, "2.11"))
20236 { # old ABI dumps
20237 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020238 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020239 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020240 { # ABI dump created with --binary option
20241 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20242 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020243 else
20244 { # default
20245 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20246 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020247
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020248 if(defined $ABI->{"Mode"}
20249 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020250 { # --ext option
20251 $ExtendedCheck = 1;
20252 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020253 if($ABI->{"Extra"}) {
20254 $ExtraDump = 1;
20255 }
20256
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020257 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020258 {
20259 $UsedDump{$LibVersion}{"L"} = $Lang;
20260 setLanguage($LibVersion, $Lang);
20261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020262 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020263 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020264 }
20265 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020266 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020268 if(not $TInfo)
20269 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020270 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020271 }
20272 my %Tid_TDid = ();
20273 foreach my $TDid (keys(%{$TInfo}))
20274 {
20275 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20276 {
20277 $MAX_ID = $Tid if($Tid>$MAX_ID);
20278 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020279 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020280 }
20281 }
20282 my %NewID = ();
20283 foreach my $Tid (keys(%Tid_TDid))
20284 {
20285 my @TDids = keys(%{$Tid_TDid{$Tid}});
20286 if($#TDids>=1)
20287 {
20288 foreach my $TDid (@TDids)
20289 {
20290 if($TDid) {
20291 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20292 }
20293 else
20294 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020295 my $ID = ++$MAX_ID;
20296
20297 $NewID{$TDid}{$Tid} = $ID;
20298 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20299 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020300 }
20301 }
20302 }
20303 else
20304 {
20305 my $TDid = $TDids[0];
20306 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20307 }
20308 }
20309 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20310 {
20311 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20312 if(defined $Info{"BaseType"})
20313 {
20314 my $Bid = $Info{"BaseType"}{"Tid"};
20315 my $BDid = $Info{"BaseType"}{"TDid"};
20316 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020317 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020318 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20319 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20320 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020321 }
20322 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020324 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020325 read_Machine_DumpInfo($ABI, $LibVersion);
20326 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020327 if(not $SymbolInfo{$LibVersion})
20328 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020329 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020330 }
20331 if(not keys(%{$SymbolInfo{$LibVersion}}))
20332 { # validation of old-version dumps
20333 if(not $ExtendedCheck) {
20334 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20335 }
20336 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020337 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020338 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020340 else
20341 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020342 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020343 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020344 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020345 }
20346 if(not $DepSymbols)
20347 { # Cannot reconstruct DepSymbols. This may result in false
20348 # positives if the old dump is for library 2. Not a problem if
20349 # old dumps are only from old libraries.
20350 $DepSymbols = {};
20351 }
20352 foreach my $Symbol (keys(%{$DepSymbols})) {
20353 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020355 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020356 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020357
20358 if(my $V = $TargetVersion{$LibVersion}) {
20359 $Descriptor{$LibVersion}{"Version"} = $V;
20360 }
20361 else {
20362 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20363 }
20364
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020365 if(not keys(%{$SkipTypes{$LibVersion}}))
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020366 { # if not defined by -skip-types option
20367 if(defined $ABI->{"SkipTypes"})
20368 {
20369 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20370 {
20371 $SkipTypes{$LibVersion}{$TName} = 1;
20372 }
20373 }
20374 if(defined $ABI->{"OpaqueTypes"})
20375 { # support for old dumps
20376 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20377 {
20378 $SkipTypes{$LibVersion}{$TName} = 1;
20379 }
20380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020381 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020382
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020383 if(not keys(%{$SkipSymbols{$LibVersion}}))
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020384 { # if not defined by -skip-symbols option
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020385 if(defined $ABI->{"SkipSymbols"}) {
20386 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20387 }
20388 if(defined $ABI->{"SkipInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020389 { # support for old dumps
20390 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20391 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020392 if(defined $ABI->{"InternalInterfaces"})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020393 { # support for old dumps
20394 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20395 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020396 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020397 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020398
20399 if(not $TargetHeaders{$LibVersion})
20400 { # if not defined by -headers-list option
20401 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20402 }
20403
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020404 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020405 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020406 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020408 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020409 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020410 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020411
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020412 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020413 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020414
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020415 if(not checkDump($LibVersion, "2.10.1")
20416 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020417 { # support for old ABI dumps: added target headers
20418 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020419 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020420 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020421
20422 if(not $ABI->{"PublicABI"})
20423 {
20424 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20425 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20426 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020428 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020429 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020430 if(defined $ABI->{"GccConstants"})
20431 { # 3.0
20432 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20433 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20434 }
20435 }
20436
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020437 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020438 if(not $NestedNameSpaces{$LibVersion})
20439 { # support for old dumps
20440 # Cannot reconstruct NameSpaces. This may affect design
20441 # of the compatibility report.
20442 $NestedNameSpaces{$LibVersion} = {};
20443 }
20444 # target system type
20445 # needed to adopt HTML report
20446 if(not $DumpSystem)
20447 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020448 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020449 }
20450 # recreate environment
20451 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20452 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020453 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020454 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020455 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20456 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020457 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020458 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020459 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020460 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20461 {
20462 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20463 setLanguage($LibVersion, "C++");
20464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020465 }
20466 }
20467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020468 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20469 {
20470 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20471 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20472 }
20473 }
20474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020475 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020476 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020477 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020478 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020479 {
20480 if(not $Symbol_Library{$LibVersion}{$MnglName}
20481 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20482 push(@VFunc, $MnglName);
20483 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020484 }
20485 }
20486 translateSymbols(@VFunc, $LibVersion);
20487 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020488 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20489
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020490 if(not checkDump($LibVersion, "3.0"))
20491 { # support for old ABI dumps
20492 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20493 {
20494 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20495 {
20496 if(ref($BaseType) eq "HASH") {
20497 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20498 }
20499 }
20500 }
20501 }
20502
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020503 if(not checkDump($LibVersion, "3.2"))
20504 { # support for old ABI dumps
20505 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20506 {
20507 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20508 {
20509 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20510 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20511 }
20512 }
20513 }
20514
20515 # repair target headers list
20516 delete($TargetHeaders{$LibVersion});
20517 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020518 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20519 }
20520 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20521 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020522 }
20523
20524 # non-target constants from anon enums
20525 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20526 {
20527 if(not $ExtraDump
20528 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20529 {
20530 delete($Constants{$LibVersion}{$Name});
20531 }
20532 }
20533 }
20534
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020535 if(not checkDump($LibVersion, "2.20"))
20536 { # support for old ABI dumps
20537 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20538 {
20539 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20540
20541 if($TType=~/Struct|Union|Enum|Typedef/)
20542 { # repair complex types first
20543 next;
20544 }
20545
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020546 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020547 {
20548 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20549 if($BType=~/Struct|Union|Enum/i)
20550 {
20551 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20552 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20553 }
20554 }
20555 }
20556 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20557 {
20558 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20559 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20560 if($TType=~/Struct|Union|Enum/) {
20561 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20562 }
20563 }
20564 }
20565
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020566 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020567 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020568 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20569 { # support for old ABI dumps < 2.0 (ACC 1.22)
20570 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20571 {
20572 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20573 {
20574 if($Access ne "public") {
20575 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20576 }
20577 }
20578 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20579 }
20580 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20581 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020582 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20583 { # support for old ABI dumps
20584 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20585 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020586 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20587 { # DWARF ABI Dumps
20588 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20589 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020590 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20591 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20592 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020593
20594 # support for old formatting of type names
20595 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20596
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020597 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20598 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020599 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020600 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20601 {
20602 if($SubId eq $TypeId)
20603 { # Fix erroneus ABI dump
20604 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20605 next;
20606 }
20607
20608 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020610 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020611 if($TInfo{"Type"} eq "MethodPtr")
20612 {
20613 if(defined $TInfo{"Param"})
20614 { # support for old ABI dumps <= 1.17
20615 if(not defined $TInfo{"Param"}{"0"})
20616 {
20617 my $Max = keys(%{$TInfo{"Param"}});
20618 foreach my $Pos (1 .. $Max) {
20619 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20620 }
20621 delete($TInfo{"Param"}{$Max});
20622 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20623 }
20624 }
20625 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020626 if($TInfo{"BaseType"} eq $TypeId)
20627 { # fix ABI dump
20628 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20629 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020630
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020631 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020632 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020633 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020634 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020635 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20636 if(not $BName)
20637 { # broken type
20638 next;
20639 }
20640 if($TInfo{"Name"} eq $BName)
20641 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020642 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020643 next;
20644 }
20645 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20646 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020647 }
20648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020649 }
20650 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20651 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020652 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020653 }
20654 }
20655
20656 if(not checkDump($LibVersion, "2.15"))
20657 { # support for old ABI dumps
20658 my %Dups = ();
20659 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20660 {
20661 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020662 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020663 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20664 { # remove template decls
20665 delete($SymbolInfo{$LibVersion}{$InfoId});
20666 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020668 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020669 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20670 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020671 { # templates
20672 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020673 }
20674 }
20675 }
20676
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020677 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20678 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020679 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20680 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20681 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20682 { # support for old ABI dumps (< 3.1)
20683 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20684 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20685 { # add "this" first parameter
20686 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20687 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20688
20689 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20690 {
20691 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20692 foreach my $Pos (reverse(0 .. $#Pos)) {
20693 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20694 }
20695 }
20696 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20697 }
20698 }
20699
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020700 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20701 { # ABI dumps have no mangled names for C-functions
20702 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20703 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020704 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20705 { # support for old ABI dumps
20706 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20707 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020708 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20709 { # DWARF ABI Dumps
20710 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20711 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020712 }
20713
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020714 $Descriptor{$LibVersion}{"Dump"} = 1;
20715}
20716
20717sub read_Machine_DumpInfo($$)
20718{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020719 my ($ABI, $LibVersion) = @_;
20720 if($ABI->{"Arch"}) {
20721 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020722 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020723 if($ABI->{"WordSize"}) {
20724 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020725 }
20726 else
20727 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020728 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020729 }
20730 if(not $WORD_SIZE{$LibVersion})
20731 { # support for old dumps (<1.23)
20732 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20733 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020734 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020735 }
20736 else
20737 {
20738 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020739 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020740 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020741 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20742 { # any "pointer"-type
20743 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020744 last;
20745 }
20746 }
20747 if($PSize)
20748 { # a pointer type size
20749 $WORD_SIZE{$LibVersion} = $PSize;
20750 }
20751 else {
20752 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20753 }
20754 }
20755 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020756 if($ABI->{"GccVersion"}) {
20757 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 }
20759}
20760
20761sub read_Libs_DumpInfo($$)
20762{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020763 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020764 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20765 if(not $Library_Symbol{$LibVersion})
20766 { # support for old dumps
20767 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020769 if(keys(%{$Library_Symbol{$LibVersion}})
20770 and not $DumpAPI) {
20771 $Descriptor{$LibVersion}{"Libs"} = "OK";
20772 }
20773}
20774
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020775sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020777 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020778
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020779 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780 and not $DumpAPI) {
20781 $Descriptor{$LibVersion}{"Headers"} = "OK";
20782 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020783 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020784 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020786 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020788
20789 if(keys(%{$ABI->{"Sources"}})
20790 and not $DumpAPI) {
20791 $Descriptor{$LibVersion}{"Sources"} = "OK";
20792 }
20793 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020794 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020795 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20796 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020798}
20799
20800sub find_libs($$$)
20801{
20802 my ($Path, $Type, $MaxDepth) = @_;
20803 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020804 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020805}
20806
20807sub createDescriptor($$)
20808{
20809 my ($LibVersion, $Path) = @_;
20810 if(not $LibVersion or not $Path
20811 or not -e $Path) {
20812 return "";
20813 }
20814 if(-d $Path)
20815 { # directory with headers files and shared objects
20816 return "
20817 <version>
20818 ".$TargetVersion{$LibVersion}."
20819 </version>
20820
20821 <headers>
20822 $Path
20823 </headers>
20824
20825 <libs>
20826 $Path
20827 </libs>";
20828 }
20829 else
20830 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020831 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020832 { # standard XML-descriptor
20833 return readFile($Path);
20834 }
20835 elsif(is_header($Path, 2, $LibVersion))
20836 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020837 $CheckHeadersOnly = 1;
20838
20839 if($LibVersion==1) {
20840 $TargetVersion{$LibVersion} = "X";
20841 }
20842
20843 if($LibVersion==2) {
20844 $TargetVersion{$LibVersion} = "Y";
20845 }
20846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020847 return "
20848 <version>
20849 ".$TargetVersion{$LibVersion}."
20850 </version>
20851
20852 <headers>
20853 $Path
20854 </headers>
20855
20856 <libs>
20857 none
20858 </libs>";
20859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020860 else
20861 { # standard XML-descriptor
20862 return readFile($Path);
20863 }
20864 }
20865}
20866
20867sub detect_lib_default_paths()
20868{
20869 my %LPaths = ();
20870 if($OSgroup eq "bsd")
20871 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020872 if(my $LdConfig = get_CmdPath("ldconfig"))
20873 {
20874 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20875 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020876 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20877 {
20878 my $Name = "lib".$1;
20879 if(not defined $LPaths{$Name}) {
20880 $LPaths{$Name} = $2;
20881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882 }
20883 }
20884 }
20885 else {
20886 printMsg("WARNING", "can't find ldconfig");
20887 }
20888 }
20889 else
20890 {
20891 if(my $LdConfig = get_CmdPath("ldconfig"))
20892 {
20893 if($SystemRoot and $OSgroup eq "linux")
20894 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20895 if(-e $SystemRoot."/etc/ld.so.conf") {
20896 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20897 }
20898 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020899 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20900 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020901 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20902 {
20903 my ($Name, $Path) = ($1, $2);
20904 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020905 if(not defined $LPaths{$Name})
20906 { # get first element from the list of available paths
20907
20908 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20909 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20910 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20911
20912 $LPaths{$Name} = $Path;
20913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020914 }
20915 }
20916 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020917 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020918 printMsg("WARNING", "can't find ldconfig");
20919 }
20920 }
20921 return \%LPaths;
20922}
20923
20924sub detect_bin_default_paths()
20925{
20926 my $EnvPaths = $ENV{"PATH"};
20927 if($OSgroup eq "beos") {
20928 $EnvPaths.=":".$ENV{"BETOOLS"};
20929 }
20930 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020931 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020932 {
20933 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020934 next if(not $Path);
20935 if($SystemRoot
20936 and $Path=~/\A\Q$SystemRoot\E\//)
20937 { # do NOT use binaries from target system
20938 next;
20939 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020940 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020941 }
20942}
20943
20944sub detect_inc_default_paths()
20945{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020946 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020947 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020948 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020949 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020950 next if(index($Line, "/cc1plus ")!=-1);
20951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020952 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20953 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030020954 my $Path = realpath_F($1);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020955 if(index($Path, "c++")!=-1
20956 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020957 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020958 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 if(not defined $MAIN_CPP_DIR
20960 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20961 $MAIN_CPP_DIR = $Path;
20962 }
20963 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020964 elsif(index($Path, "gcc")!=-1) {
20965 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020966 }
20967 else
20968 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020969 if($Path=~/local[\/\\]+include/)
20970 { # local paths
20971 next;
20972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020973 if($SystemRoot
20974 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20975 { # The GCC include path for user headers is not a part of the system root
20976 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20977 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20978 next;
20979 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020980 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020981 }
20982 }
20983 }
20984 unlink("$TMP_DIR/empty.h");
20985 return %DPaths;
20986}
20987
20988sub detect_default_paths($)
20989{
20990 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20991 my $Search = $_[0];
20992 if($Search!~/inc/) {
20993 $HSearch = 0;
20994 }
20995 if($Search!~/lib/) {
20996 $LSearch = 0;
20997 }
20998 if($Search!~/bin/) {
20999 $BSearch = 0;
21000 }
21001 if($Search!~/gcc/) {
21002 $GSearch = 0;
21003 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021004 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021005 { # <search_headers> section of the XML descriptor
21006 # do NOT search for systems headers
21007 $HSearch = 0;
21008 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021009 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030021010 { # <search_libs> section of the XML descriptor
21011 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021012 $LSearch = 0;
21013 }
21014 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
21015 { # additional search paths
21016 next if($Type eq "include" and not $HSearch);
21017 next if($Type eq "lib" and not $LSearch);
21018 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021019 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021020 }
21021 if($OSgroup ne "windows")
21022 { # unix-like
21023 foreach my $Type ("include", "lib", "bin")
21024 { # automatic detection of system "devel" directories
21025 next if($Type eq "include" and not $HSearch);
21026 next if($Type eq "lib" and not $LSearch);
21027 next if($Type eq "bin" and not $BSearch);
21028 my ($UsrDir, $RootDir) = ("/usr", "/");
21029 if($SystemRoot and $Type ne "bin")
21030 { # 1. search for target headers and libraries
21031 # 2. use host commands: ldconfig, readelf, etc.
21032 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
21033 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021034 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021035 if(-d $RootDir."/".$Type)
21036 { # if "/lib" is symbolic link
21037 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021038 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021039 }
21040 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 }
21043 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021044 if(-d $UsrDir)
21045 {
21046 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021047 if(-d $UsrDir."/".$Type)
21048 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021049 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021050 }
21051 }
21052 }
21053 }
21054 if($BSearch)
21055 {
21056 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021057 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021058 }
21059 # check environment variables
21060 if($OSgroup eq "beos")
21061 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021062 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021063 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021064 if($_ eq ".") {
21065 next;
21066 }
21067 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21068 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21069 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021070 }
21071 }
21072 if($HSearch)
21073 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021074 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21075 split(/:|;/, $ENV{"BEINCLUDES"})
21076 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021077 }
21078 if($LSearch)
21079 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021080 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21081 split(/:|;/, $ENV{"BELIBRARIES"}),
21082 split(/:|;/, $ENV{"LIBRARY_PATH"})
21083 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021084 }
21085 }
21086 if($LSearch)
21087 { # using linker to get system paths
21088 if(my $LPaths = detect_lib_default_paths())
21089 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021090 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021091 foreach my $Name (keys(%{$LPaths}))
21092 {
21093 if($SystemRoot
21094 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21095 { # wrong ldconfig configuration
21096 # check your <sysroot>/etc/ld.so.conf
21097 next;
21098 }
21099 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021100 if(my $Dir = get_dirname($LPaths->{$Name})) {
21101 $Dirs{$Dir} = 1;
21102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021103 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021104 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021105 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021106 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021107 }
21108 if($BSearch)
21109 {
21110 if($CrossGcc)
21111 { # --cross-gcc=arm-linux-gcc
21112 if(-e $CrossGcc)
21113 { # absolute or relative path
21114 $GCC_PATH = get_abs_path($CrossGcc);
21115 }
21116 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21117 { # command name
21118 $GCC_PATH = $CrossGcc;
21119 }
21120 else {
21121 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21122 }
21123 if($GCC_PATH=~/\s/) {
21124 $GCC_PATH = "\"".$GCC_PATH."\"";
21125 }
21126 }
21127 }
21128 if($GSearch)
21129 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021130 if(not $CrossGcc)
21131 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021132 $GCC_PATH = get_CmdPath("gcc");
21133 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021134 if(not $GCC_PATH)
21135 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021136 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021137 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021138 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021139 { # select the latest version
21140 @GCCs = sort {$b cmp $a} @GCCs;
21141 if(check_gcc($GCCs[0], "3"))
21142 {
21143 $GCC_PATH = $GCCs[0];
21144 last;
21145 }
21146 }
21147 }
21148 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021149 if(not $GCC_PATH) {
21150 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21151 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021152
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021153 my $GCC_Ver = get_dumpversion($GCC_PATH);
21154 if($GCC_Ver eq "4.8")
21155 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21156 my $Info = `$GCC_PATH --version`;
21157
21158 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21159 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21160 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21161 $GCC_Ver = $2;
21162 }
21163 }
21164
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021165 if($OStarget=~/macos/)
21166 {
21167 my $Info = `$GCC_PATH --version`;
21168
21169 if($Info=~/clang/i) {
21170 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21171 }
21172 }
21173
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021174 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021175 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021176 my $GccTarget = get_dumpmachine($GCC_PATH);
21177
21178 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021179 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021180 $OStarget = "linux";
21181 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021182 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021183 elsif($GccTarget=~/symbian/)
21184 {
21185 $OStarget = "symbian";
21186 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21187 }
21188
21189 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21190
21191 # check GCC version
21192 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21193 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021194 # introduced in 4.8 and fixed in 4.8.3
21195 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.");
21196
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021197 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 }
21199 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021200 else {
21201 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021202 }
21203 }
21204 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021205 {
21206 # GCC standard paths
21207 if($GCC_PATH and not $NoStdInc)
21208 {
21209 my %DPaths = detect_inc_default_paths();
21210 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21211 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21212 @DefaultIncPaths = @{$DPaths{"Inc"}};
21213 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21214 }
21215
21216 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021217 my $IncPath = "/usr/include";
21218 if($SystemRoot) {
21219 $IncPath = $SystemRoot.$IncPath;
21220 }
21221 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021222 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021223 }
21224 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021225
21226 if($ExtraInfo)
21227 {
21228 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21229 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21230 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021231}
21232
21233sub getLIB_EXT($)
21234{
21235 my $Target = $_[0];
21236 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21237 return $Ext;
21238 }
21239 return $OS_LibExt{$LIB_TYPE}{"default"};
21240}
21241
21242sub getAR_EXT($)
21243{
21244 my $Target = $_[0];
21245 if(my $Ext = $OS_Archive{$Target}) {
21246 return $Ext;
21247 }
21248 return $OS_Archive{"default"};
21249}
21250
21251sub get_dumpversion($)
21252{
21253 my $Cmd = $_[0];
21254 return "" if(not $Cmd);
21255 if($Cache{"get_dumpversion"}{$Cmd}) {
21256 return $Cache{"get_dumpversion"}{$Cmd};
21257 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021258 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021259 chomp($V);
21260 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21261}
21262
21263sub get_dumpmachine($)
21264{
21265 my $Cmd = $_[0];
21266 return "" if(not $Cmd);
21267 if($Cache{"get_dumpmachine"}{$Cmd}) {
21268 return $Cache{"get_dumpmachine"}{$Cmd};
21269 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021270 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021271 chomp($Machine);
21272 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21273}
21274
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021275sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021276{
21277 my $Cmd = $_[0];
21278 return "" if(not $Cmd);
21279 my @Options = (
21280 "--version",
21281 "-help"
21282 );
21283 foreach my $Opt (@Options)
21284 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021285 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021286 if($Info) {
21287 return 1;
21288 }
21289 }
21290 return 0;
21291}
21292
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021293sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021294{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021295 my ($Cmd, $ReqVer) = @_;
21296 return 0 if(not $Cmd or not $ReqVer);
21297 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21298 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021300 if(my $GccVer = get_dumpversion($Cmd))
21301 {
21302 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21303 if(cmpVersions($GccVer, $ReqVer)>=0) {
21304 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21305 }
21306 }
21307 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308}
21309
21310sub get_depth($)
21311{
21312 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021313 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021314 }
21315 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21316}
21317
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021318sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021319{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021320 return if($Cache{"registerGccHeaders"}); # this function should be called once
21321
21322 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021323 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021324 my @Headers = cmd_find($Path,"f");
21325 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21326 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021327 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021328 my $FileName = get_filename($HPath);
21329 if(not defined $DefaultGccHeader{$FileName})
21330 { # skip duplicated
21331 $DefaultGccHeader{$FileName} = $HPath;
21332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021333 }
21334 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021335 $Cache{"registerGccHeaders"} = 1;
21336}
21337
21338sub registerCppHeaders()
21339{
21340 return if($Cache{"registerCppHeaders"}); # this function should be called once
21341
21342 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021343 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021344 my @Headers = cmd_find($CppDir,"f");
21345 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21346 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021347 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021348 my $FileName = get_filename($Path);
21349 if(not defined $DefaultCppHeader{$FileName})
21350 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021351 $DefaultCppHeader{$FileName} = $Path;
21352 }
21353 }
21354 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021355 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021356}
21357
21358sub parse_libname($$$)
21359{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021360 return "" if(not $_[0]);
21361 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21362 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021363 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021364 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21365}
21366
21367sub parse_libname_I($$$)
21368{
21369 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021371 if($Target eq "symbian") {
21372 return parse_libname_symbian($Name, $Type);
21373 }
21374 elsif($Target eq "windows") {
21375 return parse_libname_windows($Name, $Type);
21376 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021377
21378 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021379 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021380 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 { # libSDL-1.2.so.0.7.1
21382 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021383 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021384 if($Type eq "name")
21385 { # libSDL-1.2
21386 # libwbxml2
21387 return $2;
21388 }
21389 elsif($Type eq "name+ext")
21390 { # libSDL-1.2.so
21391 # libwbxml2.so
21392 return $1;
21393 }
21394 elsif($Type eq "version")
21395 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021396 if(defined $7
21397 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021398 { # 0.7.1
21399 return $7;
21400 }
21401 else
21402 { # libc-2.5.so (=>2.5 version)
21403 my $MV = $5;
21404 $MV=~s/\A[\-\_]+//g;
21405 return $MV;
21406 }
21407 }
21408 elsif($Type eq "short")
21409 { # libSDL
21410 # libwbxml2
21411 return $3;
21412 }
21413 elsif($Type eq "shortest")
21414 { # SDL
21415 # wbxml
21416 return shortest_name($3);
21417 }
21418 }
21419 return "";# error
21420}
21421
21422sub parse_libname_symbian($$)
21423{
21424 my ($Name, $Type) = @_;
21425 my $Ext = getLIB_EXT("symbian");
21426 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21427 { # libpthread{00010001}.dso
21428 if($Type eq "name")
21429 { # libpthread{00010001}
21430 return $2;
21431 }
21432 elsif($Type eq "name+ext")
21433 { # libpthread{00010001}.dso
21434 return $1;
21435 }
21436 elsif($Type eq "version")
21437 { # 00010001
21438 my $V = $4;
21439 $V=~s/\{(.+)\}/$1/;
21440 return $V;
21441 }
21442 elsif($Type eq "short")
21443 { # libpthread
21444 return $3;
21445 }
21446 elsif($Type eq "shortest")
21447 { # pthread
21448 return shortest_name($3);
21449 }
21450 }
21451 return "";# error
21452}
21453
21454sub parse_libname_windows($$)
21455{
21456 my ($Name, $Type) = @_;
21457 my $Ext = getLIB_EXT("windows");
21458 if($Name=~/((.+?)\.$Ext)\Z/)
21459 { # netapi32.dll
21460 if($Type eq "name")
21461 { # netapi32
21462 return $2;
21463 }
21464 elsif($Type eq "name+ext")
21465 { # netapi32.dll
21466 return $1;
21467 }
21468 elsif($Type eq "version")
21469 { # DLL version embedded
21470 # at binary-level
21471 return "";
21472 }
21473 elsif($Type eq "short")
21474 { # netapi32
21475 return $2;
21476 }
21477 elsif($Type eq "shortest")
21478 { # netapi
21479 return shortest_name($2);
21480 }
21481 }
21482 return "";# error
21483}
21484
21485sub shortest_name($)
21486{
21487 my $Name = $_[0];
21488 # remove prefix
21489 $Name=~s/\A(lib|open)//;
21490 # remove suffix
21491 $Name=~s/[\W\d_]+\Z//i;
21492 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21493 return $Name;
21494}
21495
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021496sub createSymbolsList($$$$$)
21497{
21498 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021500 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021501 prepareSymbols(1);
21502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021503 my %SymbolHeaderLib = ();
21504 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021506 # Get List
21507 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21508 {
21509 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021510 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021511 next;
21512 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021513 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021514 { # skip other symbols
21515 next;
21516 }
21517 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21518 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021519 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021520 next;
21521 }
21522 my $DyLib = $Symbol_Library{1}{$Symbol};
21523 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021524 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021525 next;
21526 }
21527 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21528 $Total+=1;
21529 }
21530 # Draw List
21531 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21532 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21533 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21534 {
21535 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21536 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021537 my %NS_Symbol = ();
21538 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021539 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021540 }
21541 foreach my $NameSpace (sort keys(%NS_Symbol))
21542 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021543 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021544 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21545 foreach my $Symbol (@SortedInterfaces)
21546 {
21547 my $SubReport = "";
21548 my $Signature = get_Signature($Symbol, 1);
21549 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021550 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021551 }
21552 if($Symbol=~/\A(_Z|\?)/)
21553 {
21554 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021555 $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 +040021556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021557 else {
21558 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21559 }
21560 }
21561 else
21562 {
21563 if($Signature) {
21564 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21565 }
21566 else {
21567 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21568 }
21569 }
21570 $SYMBOLS_LIST .= $SubReport;
21571 }
21572 }
21573 $SYMBOLS_LIST .= "<br/>\n";
21574 }
21575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021576 # clear info
21577 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21578 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21579 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21580 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021581 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021582 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021583 my $CssStyles = readModule("Styles", "SymbolsList.css");
21584 my $JScripts = readModule("Scripts", "Sections.js");
21585 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021586 my $Title = "$LName: public symbols";
21587 my $Keywords = "$LName, API, symbols";
21588 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021589 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021590 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021591 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021592 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021593 writeFile($SaveTo, $SYMBOLS_LIST);
21594}
21595
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021596sub add_target_libs($)
21597{
21598 foreach (@{$_[0]}) {
21599 $TargetLibs{$_} = 1;
21600 }
21601}
21602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021603sub is_target_lib($)
21604{
21605 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021606 if(not $LName) {
21607 return 0;
21608 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021609 if($OSgroup eq "windows") {
21610 $LName = lc($LName);
21611 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021612 if($TargetLibraryName
21613 and $LName!~/\Q$TargetLibraryName\E/) {
21614 return 0;
21615 }
21616 if(keys(%TargetLibs)
21617 and not $TargetLibs{$LName}
21618 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21619 return 0;
21620 }
21621 return 1;
21622}
21623
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021624sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021625{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021626 my ($H, $V) = @_;
21627 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021628 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021629 if($TargetHeaders{$V}{$H}) {
21630 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021631 }
21632 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021633 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634}
21635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021636sub readLibs($)
21637{
21638 my $LibVersion = $_[0];
21639 if($OStarget eq "windows")
21640 { # dumpbin.exe will crash
21641 # without VS Environment
21642 check_win32_env();
21643 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021644 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021645 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021646 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021647}
21648
21649sub dump_sorting($)
21650{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021651 my $Hash = $_[0];
21652 return [] if(not $Hash);
21653 my @Keys = keys(%{$Hash});
21654 return [] if($#Keys<0);
21655 if($Keys[0]=~/\A\d+\Z/)
21656 { # numbers
21657 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021658 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021659 else
21660 { # strings
21661 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021662 }
21663}
21664
21665sub printMsg($$)
21666{
21667 my ($Type, $Msg) = @_;
21668 if($Type!~/\AINFO/) {
21669 $Msg = $Type.": ".$Msg;
21670 }
21671 if($Type!~/_C\Z/) {
21672 $Msg .= "\n";
21673 }
21674 if($Quiet)
21675 { # --quiet option
21676 appendFile($COMMON_LOG_PATH, $Msg);
21677 }
21678 else
21679 {
21680 if($Type eq "ERROR") {
21681 print STDERR $Msg;
21682 }
21683 else {
21684 print $Msg;
21685 }
21686 }
21687}
21688
21689sub exitStatus($$)
21690{
21691 my ($Code, $Msg) = @_;
21692 printMsg("ERROR", $Msg);
21693 exit($ERROR_CODE{$Code});
21694}
21695
21696sub exitReport()
21697{ # the tool has run without any errors
21698 printReport();
21699 if($COMPILE_ERRORS)
21700 { # errors in headers may add false positives/negatives
21701 exit($ERROR_CODE{"Compile_Error"});
21702 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021703 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21704 { # --binary
21705 exit($ERROR_CODE{"Incompatible"});
21706 }
21707 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21708 { # --source
21709 exit($ERROR_CODE{"Incompatible"});
21710 }
21711 elsif($RESULT{"Source"}{"Problems"}
21712 or $RESULT{"Binary"}{"Problems"})
21713 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021714 exit($ERROR_CODE{"Incompatible"});
21715 }
21716 else {
21717 exit($ERROR_CODE{"Compatible"});
21718 }
21719}
21720
21721sub readRules($)
21722{
21723 my $Kind = $_[0];
21724 if(not -f $RULES_PATH{$Kind}) {
21725 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21726 }
21727 my $Content = readFile($RULES_PATH{$Kind});
21728 while(my $Rule = parseTag(\$Content, "rule"))
21729 {
21730 my $RId = parseTag(\$Rule, "id");
21731 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21732 foreach my $Prop (@Properties) {
21733 if(my $Value = parseTag(\$Rule, lc($Prop)))
21734 {
21735 $Value=~s/\n[ ]*//;
21736 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21737 }
21738 }
21739 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21740 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21741 }
21742 else {
21743 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21744 }
21745 }
21746}
21747
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021748sub getReportPath($)
21749{
21750 my $Level = $_[0];
21751 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21752 if($Level eq "Binary")
21753 {
21754 if($BinaryReportPath)
21755 { # --bin-report-path
21756 return $BinaryReportPath;
21757 }
21758 elsif($OutputReportPath)
21759 { # --report-path
21760 return $OutputReportPath;
21761 }
21762 else
21763 { # default
21764 return $Dir."/abi_compat_report.$ReportFormat";
21765 }
21766 }
21767 elsif($Level eq "Source")
21768 {
21769 if($SourceReportPath)
21770 { # --src-report-path
21771 return $SourceReportPath;
21772 }
21773 elsif($OutputReportPath)
21774 { # --report-path
21775 return $OutputReportPath;
21776 }
21777 else
21778 { # default
21779 return $Dir."/src_compat_report.$ReportFormat";
21780 }
21781 }
21782 else
21783 {
21784 if($OutputReportPath)
21785 { # --report-path
21786 return $OutputReportPath;
21787 }
21788 else
21789 { # default
21790 return $Dir."/compat_report.$ReportFormat";
21791 }
21792 }
21793}
21794
21795sub printStatMsg($)
21796{
21797 my $Level = $_[0];
21798 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21799}
21800
21801sub listAffected($)
21802{
21803 my $Level = $_[0];
21804 my $List = "";
21805 foreach (keys(%{$TotalAffected{$Level}}))
21806 {
21807 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21808 { # skip "Low"-severity problems
21809 next;
21810 }
21811 $List .= "$_\n";
21812 }
21813 my $Dir = get_dirname(getReportPath($Level));
21814 if($Level eq "Binary") {
21815 writeFile($Dir."/abi_affected.txt", $List);
21816 }
21817 elsif($Level eq "Source") {
21818 writeFile($Dir."/src_affected.txt", $List);
21819 }
21820}
21821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021822sub printReport()
21823{
21824 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021825 createReport();
21826 if($JoinReport or $DoubleReport)
21827 {
21828 if($RESULT{"Binary"}{"Problems"}
21829 or $RESULT{"Source"}{"Problems"}) {
21830 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021832 else {
21833 printMsg("INFO", "result: COMPATIBLE");
21834 }
21835 printStatMsg("Binary");
21836 printStatMsg("Source");
21837 if($ListAffected)
21838 { # --list-affected
21839 listAffected("Binary");
21840 listAffected("Source");
21841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021843 elsif($BinaryOnly)
21844 {
21845 if($RESULT{"Binary"}{"Problems"}) {
21846 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21847 }
21848 else {
21849 printMsg("INFO", "result: COMPATIBLE");
21850 }
21851 printStatMsg("Binary");
21852 if($ListAffected)
21853 { # --list-affected
21854 listAffected("Binary");
21855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021857 elsif($SourceOnly)
21858 {
21859 if($RESULT{"Source"}{"Problems"}) {
21860 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21861 }
21862 else {
21863 printMsg("INFO", "result: COMPATIBLE");
21864 }
21865 printStatMsg("Source");
21866 if($ListAffected)
21867 { # --list-affected
21868 listAffected("Source");
21869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021871 if($StdOut)
21872 {
21873 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021874 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021875 printMsg("INFO", "compatibility report has been generated to stdout");
21876 }
21877 else
21878 { # default
21879 printMsg("INFO", "compatibility reports have been generated to stdout");
21880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021882 else
21883 {
21884 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021885 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021886 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21887 }
21888 elsif($DoubleReport)
21889 { # default
21890 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21891 }
21892 elsif($BinaryOnly)
21893 { # --binary
21894 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21895 }
21896 elsif($SourceOnly)
21897 { # --source
21898 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021900 }
21901}
21902
21903sub check_win32_env()
21904{
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030021905 if(not $ENV{"VCINSTALLDIR"}
21906 or not $ENV{"INCLUDE"}) {
21907 exitStatus("Error", "can't start without VC environment (vcvars64.bat)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021908 }
21909}
21910
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021911sub diffSets($$)
21912{
21913 my ($S1, $S2) = @_;
21914 my @SK1 = keys(%{$S1});
21915 my @SK2 = keys(%{$S2});
21916 if($#SK1!=$#SK2) {
21917 return 1;
21918 }
21919 foreach my $K1 (@SK1)
21920 {
21921 if(not defined $S2->{$K1}) {
21922 return 1;
21923 }
21924 }
21925 return 0;
21926}
21927
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021928sub defaultDumpPath($$)
21929{
21930 my ($N, $V) = @_;
21931 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21932}
21933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021934sub create_ABI_Dump()
21935{
21936 if(not -e $DumpAPI) {
21937 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21938 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021939
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021940 if(isDump($DumpAPI)) {
21941 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021942 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021943 else {
21944 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021945 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021946
21947 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021948 { # set to default: N
21949 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021950 }
21951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021952 initLogging(1);
21953 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021954
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021955 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021956 if($OutputDumpPath)
21957 { # user defined path
21958 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021959 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021960 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21961
21962 if(not $Archive and not $StdOut)
21963 { # check archive utilities
21964 if($OSgroup eq "windows")
21965 { # using zip
21966 my $ZipCmd = get_CmdPath("zip");
21967 if(not $ZipCmd) {
21968 exitStatus("Not_Found", "can't find \"zip\"");
21969 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021970 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021971 else
21972 { # using tar and gzip
21973 my $TarCmd = get_CmdPath("tar");
21974 if(not $TarCmd) {
21975 exitStatus("Not_Found", "can't find \"tar\"");
21976 }
21977 my $GzipCmd = get_CmdPath("gzip");
21978 if(not $GzipCmd) {
21979 exitStatus("Not_Found", "can't find \"gzip\"");
21980 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021981 }
21982 }
21983
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021984 if(not $Descriptor{1}{"Dump"})
21985 {
21986 if(not $CheckHeadersOnly) {
21987 readLibs(1);
21988 }
21989 if($CheckHeadersOnly) {
21990 setLanguage(1, "C++");
21991 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021992 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021993 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021994 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021995 if(not $Descriptor{1}{"Dump"})
21996 {
21997 if($Descriptor{1}{"Headers"}) {
21998 readHeaders(1);
21999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022000 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022001 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022002 if(not keys(%{$SymbolInfo{1}}))
22003 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022004 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022005 {
22006 if($CheckHeadersOnly) {
22007 exitStatus("Empty_Set", "the set of public symbols is empty");
22008 }
22009 else {
22010 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
22011 }
22012 }
22013 }
22014 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022015 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022016 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
22017 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022018 if($ExtraDump)
22019 { # add unmangled names to the ABI dump
22020 my @Names = ();
22021 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22022 {
22023 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
22024 push(@Names, $MnglName);
22025 }
22026 }
22027 translateSymbols(@Names, 1);
22028 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
22029 {
22030 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
22031 {
22032 if(my $Unmangled = $tr_name{$MnglName})
22033 {
22034 if($MnglName ne $Unmangled) {
22035 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
22036 }
22037 }
22038 }
22039 }
22040 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022041
22042 my %GccConstants = (); # built-in GCC constants
22043 foreach my $Name (keys(%{$Constants{1}}))
22044 {
22045 if(not defined $Constants{1}{$Name}{"Header"})
22046 {
22047 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
22048 delete($Constants{1}{$Name});
22049 }
22050 }
22051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022052 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022053 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022054 "TypeInfo" => $TypeInfo{1},
22055 "SymbolInfo" => $SymbolInfo{1},
22056 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022057 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022058 "SymbolVersion" => $SymVer{1},
22059 "LibraryVersion" => $Descriptor{1}{"Version"},
22060 "LibraryName" => $TargetLibraryName,
22061 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022062 "SkipTypes" => $SkipTypes{1},
22063 "SkipSymbols" => $SkipSymbols{1},
22064 "SkipNameSpaces" => $SkipNameSpaces{1},
22065 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 "Headers" => \%HeadersInfo,
22067 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022068 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022069 "NameSpaces" => $NestedNameSpaces{1},
22070 "Target" => $OStarget,
22071 "Arch" => getArch(1),
22072 "WordSize" => $WORD_SIZE{1},
22073 "GccVersion" => get_dumpversion($GCC_PATH),
22074 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22075 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22076 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022077 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022078 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022079 }
22080 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022081 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022083 if($ExtendedCheck)
22084 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022085 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022086 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022087 if($BinaryOnly)
22088 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022089 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022090 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022091 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022092 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022093 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022094 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22095 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022096 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022097
22098 my $ABI_DUMP = "";
22099 if($UseXML)
22100 {
22101 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022102 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022104 else
22105 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022106 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022108 if($StdOut)
22109 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022110 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 printMsg("INFO", "ABI dump has been generated to stdout");
22112 return;
22113 }
22114 else
22115 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022116 my ($DDir, $DName) = separate_path($DumpPath);
22117 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022118 if(not $Archive) {
22119 $DPath = $DumpPath;
22120 }
22121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022122 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022123
22124 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022125 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022126 close(DUMP);
22127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022128 if(not -s $DPath) {
22129 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22130 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022131 if($Archive) {
22132 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022133 }
22134
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022135 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022136 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022137 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022138 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022139 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022140 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022141 # 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 +040022142 }
22143}
22144
22145sub quickEmptyReports()
22146{ # Quick "empty" reports
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022147 # ~4 times faster than merging equal dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022148 # NOTE: the dump contains the "LibraryVersion" attribute
22149 # if you change the version, then your dump will be different
22150 # OVERCOME: use -v1 and v2 options for comparing dumps
22151 # and don't change version in the XML descriptor (and dumps)
22152 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022153 if($Descriptor{1}{"Path"} eq $Descriptor{2}{"Path"}
22154 or -s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022155 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022156 my $FilePath1 = $Descriptor{1}{"Path"};
22157 my $FilePath2 = $Descriptor{2}{"Path"};
22158
22159 if(not isDump_U($FilePath1)) {
22160 $FilePath1 = unpackDump($FilePath1);
22161 }
22162
22163 if(not isDump_U($FilePath2)) {
22164 $FilePath2 = unpackDump($FilePath2);
22165 }
22166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022167 if($FilePath1 and $FilePath2)
22168 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022169 my $Line = readLineNum($FilePath1, 0);
22170 if($Line=~/xml/)
22171 { # XML format
22172 # is not supported yet
22173 return;
22174 }
22175
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022176 local $/ = undef;
22177
22178 open(DUMP1, $FilePath1);
22179 my $Content1 = <DUMP1>;
22180 close(DUMP1);
22181
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022182 my $Eq = 0;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022183
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022184 if($FilePath1 eq $FilePath2) {
22185 $Eq = 1;
22186 }
22187
22188 if(not $Eq)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022189 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022190 open(DUMP2, $FilePath2);
22191 my $Content2 = <DUMP2>;
22192 close(DUMP2);
22193
22194 if($Content1 eq $Content2) {
22195 $Eq = 1;
22196 }
22197
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022198 # clean memory
22199 undef $Content2;
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022200 }
22201
22202 if($Eq)
22203 {
22204 printMsg("INFO", "Input ABI dumps are equal, so generating quick empty report");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022205 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022206 my $ABIdump = eval($Content1);
22207
22208 # clean memory
22209 undef $Content1;
22210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022211 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022212 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 +040022213 }
22214 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022215 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022216 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22217 }
22218 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022219 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022220 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22221 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022222 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022223
22224 foreach (keys(%{$Registered_Headers{1}})) {
22225 $TargetHeaders{1}{$_} = 1;
22226 }
22227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022228 read_Libs_DumpInfo($ABIdump, 1);
22229 read_Machine_DumpInfo($ABIdump, 1);
22230 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022231
22232 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22233 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22234
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022235 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22236 {
22237 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22238 {
22239 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22240 next;
22241 }
22242 }
22243
22244 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22245 if($Access ne "private")
22246 {
22247 $CheckedSymbols{"Binary"}{$S} = 1;
22248 $CheckedSymbols{"Source"}{$S} = 1;
22249 }
22250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022251
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022252 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22253 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022254
22255 if(defined $ABIdump->{"ABI_DUMPER_VERSION"})
22256 {
22257 $UsedDump{1}{"DWARF"} = 1;
22258 $UsedDump{2}{"DWARF"} = 1;
22259
22260 $UsedDump{1}{"M"} = $ABIdump->{"LibraryName"};
22261 $UsedDump{2}{"M"} = $ABIdump->{"LibraryName"};
22262 }
22263
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022264 exitReport();
22265 }
22266 }
22267 }
22268}
22269
22270sub initLogging($)
22271{
22272 my $LibVersion = $_[0];
22273 # create log directory
22274 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22275 if($OutputLogPath{$LibVersion})
22276 { # user-defined by -log-path option
22277 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22278 }
22279 if($LogMode ne "n") {
22280 mkpath($LOG_DIR);
22281 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022282 $LOG_PATH{$LibVersion} = join_P(get_abs_path($LOG_DIR), $LOG_FILE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022283 if($Debug)
22284 { # debug directory
22285 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022286
22287 if(not $ExtraInfo)
22288 { # enable --extra-info
22289 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022291 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022292 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022293}
22294
22295sub writeLog($$)
22296{
22297 my ($LibVersion, $Msg) = @_;
22298 if($LogMode ne "n") {
22299 appendFile($LOG_PATH{$LibVersion}, $Msg);
22300 }
22301}
22302
22303sub resetLogging($)
22304{
22305 my $LibVersion = $_[0];
22306 if($LogMode!~/a|n/)
22307 { # remove old log
22308 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022309 if($Debug) {
22310 rmtree($DEBUG_PATH{$LibVersion});
22311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022312 }
22313}
22314
22315sub printErrorLog($)
22316{
22317 my $LibVersion = $_[0];
22318 if($LogMode ne "n") {
22319 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22320 }
22321}
22322
22323sub isDump($)
22324{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022325 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22326 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022327 return $1;
22328 }
22329 return 0;
22330}
22331
22332sub isDump_U($)
22333{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022334 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022335 return $1;
22336 }
22337 return 0;
22338}
22339
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022340sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022341{
22342 # read input XML descriptors or ABI dumps
22343 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022344 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022345 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022346 if(not -e $Descriptor{1}{"Path"}) {
22347 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022348 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022350 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022351 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022352 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022353 if(not -e $Descriptor{2}{"Path"}) {
22354 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022355 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022357 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022358
22359 if(not defined $DisableQuickEmptyReport)
22360 {
22361 if(isDump($Descriptor{1}{"Path"})
22362 and isDump($Descriptor{2}{"Path"}))
22363 { # optimization: equal ABI dumps
22364 quickEmptyReports();
22365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022366 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022368 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022369
22370 if(isDump($Descriptor{1}{"Path"})) {
22371 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022372 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022373 else {
22374 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22375 }
22376
22377 if(isDump($Descriptor{2}{"Path"})) {
22378 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22379 }
22380 else {
22381 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022382 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022383
22384 if(not $Descriptor{1}{"Version"})
22385 { # set to default: X
22386 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022387 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022388 }
22389
22390 if(not $Descriptor{2}{"Version"})
22391 { # set to default: Y
22392 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022393 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022394 }
22395
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022396 if(not $UsedDump{1}{"V"}) {
22397 initLogging(1);
22398 }
22399
22400 if(not $UsedDump{2}{"V"}) {
22401 initLogging(2);
22402 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022403
22404 # check input data
22405 if(not $Descriptor{1}{"Headers"}) {
22406 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022407 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022408 if(not $Descriptor{2}{"Headers"}) {
22409 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022410 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022411
22412 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022413 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022414 if(not $Descriptor{1}{"Libs"}) {
22415 exitStatus("Error", "can't find libraries info in descriptor d1");
22416 }
22417 if(not $Descriptor{2}{"Libs"}) {
22418 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022419 }
22420 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022422 if($UseDumps)
22423 { # --use-dumps
22424 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022425 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22426 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022427
22428 unlink($DumpPath1);
22429 unlink($DumpPath2);
22430
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022431 my $pid = fork();
22432 if($pid)
22433 { # dump on two CPU cores
22434 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22435 if($RelativeDirectory{1}) {
22436 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22437 }
22438 if($OutputLogPath{1}) {
22439 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22440 }
22441 if($CrossGcc) {
22442 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22443 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022444 if($Quiet)
22445 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022446 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022447 @PARAMS = (@PARAMS, "-logging-mode", "a");
22448 }
22449 elsif($LogMode and $LogMode ne "w")
22450 { # "w" is default
22451 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022452 }
22453 if($ExtendedCheck) {
22454 @PARAMS = (@PARAMS, "-extended");
22455 }
22456 if($UserLang) {
22457 @PARAMS = (@PARAMS, "-lang", $UserLang);
22458 }
22459 if($TargetVersion{1}) {
22460 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22461 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022462 if($BinaryOnly) {
22463 @PARAMS = (@PARAMS, "-binary");
22464 }
22465 if($SourceOnly) {
22466 @PARAMS = (@PARAMS, "-source");
22467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022468 if($SortDump) {
22469 @PARAMS = (@PARAMS, "-sort");
22470 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022471 if($DumpFormat and $DumpFormat ne "perl") {
22472 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22473 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022474 if($CheckHeadersOnly) {
22475 @PARAMS = (@PARAMS, "-headers-only");
22476 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022477 if($Debug)
22478 {
22479 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022480 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022482 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022483 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022484 exit(1);
22485 }
22486 }
22487 else
22488 { # child
22489 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22490 if($RelativeDirectory{2}) {
22491 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22492 }
22493 if($OutputLogPath{2}) {
22494 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22495 }
22496 if($CrossGcc) {
22497 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22498 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022499 if($Quiet)
22500 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022501 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022502 @PARAMS = (@PARAMS, "-logging-mode", "a");
22503 }
22504 elsif($LogMode and $LogMode ne "w")
22505 { # "w" is default
22506 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022507 }
22508 if($ExtendedCheck) {
22509 @PARAMS = (@PARAMS, "-extended");
22510 }
22511 if($UserLang) {
22512 @PARAMS = (@PARAMS, "-lang", $UserLang);
22513 }
22514 if($TargetVersion{2}) {
22515 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022517 if($BinaryOnly) {
22518 @PARAMS = (@PARAMS, "-binary");
22519 }
22520 if($SourceOnly) {
22521 @PARAMS = (@PARAMS, "-source");
22522 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022523 if($SortDump) {
22524 @PARAMS = (@PARAMS, "-sort");
22525 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022526 if($DumpFormat and $DumpFormat ne "perl") {
22527 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22528 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022529 if($CheckHeadersOnly) {
22530 @PARAMS = (@PARAMS, "-headers-only");
22531 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022532 if($Debug)
22533 {
22534 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022535 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022536 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022537 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022538 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022539 exit(1);
22540 }
22541 else {
22542 exit(0);
22543 }
22544 }
22545 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022546
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022547 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022548 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22549 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022550 if($TargetTitle ne $TargetLibraryName) {
22551 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022552 }
22553 if($ShowRetVal) {
22554 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22555 }
22556 if($CrossGcc) {
22557 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22558 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022559 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22560 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022561 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022562 }
22563 if($ReportFormat and $ReportFormat ne "html")
22564 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022565 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022567 if($OutputReportPath) {
22568 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22569 }
22570 if($BinaryReportPath) {
22571 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22572 }
22573 if($SourceReportPath) {
22574 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22575 }
22576 if($LoggingPath) {
22577 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22578 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022579 if($CheckHeadersOnly) {
22580 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22581 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022582 if($BinaryOnly) {
22583 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22584 }
22585 if($SourceOnly) {
22586 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22587 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022588 if($Debug)
22589 {
22590 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22591 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022593 system("perl", $0, @CMP_PARAMS);
22594 exit($?>>8);
22595 }
22596 if(not $Descriptor{1}{"Dump"}
22597 or not $Descriptor{2}{"Dump"})
22598 { # need GCC toolchain to analyze
22599 # header files and libraries
22600 detect_default_paths("inc|lib|gcc");
22601 }
22602 if(not $Descriptor{1}{"Dump"})
22603 {
22604 if(not $CheckHeadersOnly) {
22605 readLibs(1);
22606 }
22607 if($CheckHeadersOnly) {
22608 setLanguage(1, "C++");
22609 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022610 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022611 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022612 }
22613 if(not $Descriptor{2}{"Dump"})
22614 {
22615 if(not $CheckHeadersOnly) {
22616 readLibs(2);
22617 }
22618 if($CheckHeadersOnly) {
22619 setLanguage(2, "C++");
22620 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022621 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022622 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022623 }
22624 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22625 { # support for old ABI dumps
22626 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022627 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022628 {
22629 $WORD_SIZE{1} = $WORD_SIZE{2};
22630 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22631 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022632 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022633 {
22634 $WORD_SIZE{2} = $WORD_SIZE{1};
22635 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22636 }
22637 }
22638 elsif(not $WORD_SIZE{1}
22639 and not $WORD_SIZE{2})
22640 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022641 $WORD_SIZE{1} = "4";
22642 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022643 }
22644 if($Descriptor{1}{"Dump"})
22645 { # support for old ABI dumps
22646 prepareTypes(1);
22647 }
22648 if($Descriptor{2}{"Dump"})
22649 { # support for old ABI dumps
22650 prepareTypes(2);
22651 }
22652 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22653 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22654 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022655 # process input data
22656 if($Descriptor{1}{"Headers"}
22657 and not $Descriptor{1}{"Dump"}) {
22658 readHeaders(1);
22659 }
22660 if($Descriptor{2}{"Headers"}
22661 and not $Descriptor{2}{"Dump"}) {
22662 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022664
22665 # clean memory
22666 %SystemHeaders = ();
22667 %mangled_name_gcc = ();
22668
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022669 prepareSymbols(1);
22670 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022671
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022672 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022673 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022674
22675 # Virtual Tables
22676 registerVTable(1);
22677 registerVTable(2);
22678
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022679 if(not checkDump(1, "1.22")
22680 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022681 { # support for old ABI dumps
22682 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22683 {
22684 if($ClassName=~/</)
22685 { # templates
22686 if(not defined $VirtualTable{1}{$ClassName})
22687 { # synchronize
22688 delete($VirtualTable{2}{$ClassName});
22689 }
22690 }
22691 }
22692 }
22693
22694 registerOverriding(1);
22695 registerOverriding(2);
22696
22697 setVirtFuncPositions(1);
22698 setVirtFuncPositions(2);
22699
22700 # Other
22701 addParamNames(1);
22702 addParamNames(2);
22703
22704 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022705}
22706
22707sub compareAPIs($)
22708{
22709 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022710
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022711 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022712 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022713
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022714 if($Level eq "Binary") {
22715 printMsg("INFO", "comparing ABIs ...");
22716 }
22717 else {
22718 printMsg("INFO", "comparing APIs ...");
22719 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022720
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022721 if($CheckHeadersOnly
22722 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022723 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022724 detectAdded_H($Level);
22725 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022726 }
22727 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022728 { # added/removed in libs
22729 detectAdded($Level);
22730 detectRemoved($Level);
22731 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022732
22733 mergeSymbols($Level);
22734 if(keys(%{$CheckedSymbols{$Level}})) {
22735 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022736 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022737
22738 $Cache{"mergeTypes"} = (); # free memory
22739
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022740 if($CheckHeadersOnly
22741 or $Level eq "Source")
22742 { # added/removed in headers
22743 mergeHeaders($Level);
22744 }
22745 else
22746 { # added/removed in libs
22747 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022748 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022749
22750 foreach my $S (keys(%{$CompatProblems{$Level}}))
22751 {
22752 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22753 {
22754 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22755 {
22756 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22757 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22758 }
22759 }
22760 }
22761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022762}
22763
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022764sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022765{
22766 my %Opts = (
22767 "OStarget"=>$OStarget,
22768 "Debug"=>$Debug,
22769 "Quiet"=>$Quiet,
22770 "LogMode"=>$LogMode,
22771 "CheckHeadersOnly"=>$CheckHeadersOnly,
22772
22773 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022774 "GCC_PATH"=>$GCC_PATH,
22775 "TargetSysInfo"=>$TargetSysInfo,
22776 "CrossPrefix"=>$CrossPrefix,
22777 "TargetLibraryName"=>$TargetLibraryName,
22778 "CrossGcc"=>$CrossGcc,
22779 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022780 "NoStdInc"=>$NoStdInc,
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022781 "CppCompat"=>$CppCompat,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022782
22783 "BinaryOnly" => $BinaryOnly,
22784 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022785 );
22786 return \%Opts;
22787}
22788
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022789sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022790{
22791 my %CODE_ERROR = reverse(%ERROR_CODE);
22792 return $CODE_ERROR{$_[0]};
22793}
22794
22795sub scenario()
22796{
22797 if($StdOut)
22798 { # enable quiet mode
22799 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022800 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022801 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022802 if(not $LogMode)
22803 { # default
22804 $LogMode = "w";
22805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022806 if($UserLang)
22807 { # --lang=C++
22808 $UserLang = uc($UserLang);
22809 $COMMON_LANGUAGE{1}=$UserLang;
22810 $COMMON_LANGUAGE{2}=$UserLang;
22811 }
22812 if($LoggingPath)
22813 {
22814 $OutputLogPath{1} = $LoggingPath;
22815 $OutputLogPath{2} = $LoggingPath;
22816 if($Quiet) {
22817 $COMMON_LOG_PATH = $LoggingPath;
22818 }
22819 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022820
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022821 if($Quick) {
22822 $ADD_TMPL_INSTANCES = 0;
22823 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022824 if($OutputDumpPath)
22825 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022826 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022827 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22828 }
22829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022830 if($BinaryOnly and $SourceOnly)
22831 { # both --binary and --source
22832 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022833 if(not $CmpSystems)
22834 {
22835 $BinaryOnly = 0;
22836 $SourceOnly = 0;
22837 }
22838
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022839 $DoubleReport = 1;
22840 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022841
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022842 if($OutputReportPath)
22843 { # --report-path
22844 $DoubleReport = 0;
22845 $JoinReport = 1;
22846 }
22847 }
22848 elsif($BinaryOnly or $SourceOnly)
22849 { # --binary or --source
22850 $DoubleReport = 0;
22851 $JoinReport = 0;
22852 }
22853 if($UseXML)
22854 { # --xml option
22855 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022856 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022858 if($ReportFormat)
22859 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022860 $ReportFormat = lc($ReportFormat);
22861 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022862 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022864 if($ReportFormat eq "htm")
22865 { # HTM == HTML
22866 $ReportFormat = "html";
22867 }
22868 elsif($ReportFormat eq "xml")
22869 { # --report-format=XML equal to --xml
22870 $UseXML = 1;
22871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022872 }
22873 else
22874 { # default: HTML
22875 $ReportFormat = "html";
22876 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022877 if($DumpFormat)
22878 { # validate
22879 $DumpFormat = lc($DumpFormat);
22880 if($DumpFormat!~/\A(xml|perl)\Z/) {
22881 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22882 }
22883 if($DumpFormat eq "xml")
22884 { # --dump-format=XML equal to --xml
22885 $UseXML = 1;
22886 }
22887 }
22888 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022889 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022890 $DumpFormat = "perl";
22891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022892 if($Quiet and $LogMode!~/a|n/)
22893 { # --quiet log
22894 if(-f $COMMON_LOG_PATH) {
22895 unlink($COMMON_LOG_PATH);
22896 }
22897 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022898 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022899 $CheckUndefined = 1;
22900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022901 if($TestTool and $UseDumps)
22902 { # --test && --use-dumps == --test-dump
22903 $TestDump = 1;
22904 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022905 if($Tolerant)
22906 { # enable all
22907 $Tolerance = 1234;
22908 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022909 if($Help)
22910 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022911 HELP_MESSAGE();
22912 exit(0);
22913 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022914 if($InfoMsg)
22915 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022916 INFO_MESSAGE();
22917 exit(0);
22918 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022919 if($ShowVersion)
22920 {
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022921 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 +040022922 exit(0);
22923 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022924 if($DumpVersion)
22925 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022926 printMsg("INFO", $TOOL_VERSION);
22927 exit(0);
22928 }
22929 if($ExtendedCheck) {
22930 $CheckHeadersOnly = 1;
22931 }
22932 if($SystemRoot_Opt)
22933 { # user defined root
22934 if(not -e $SystemRoot_Opt) {
22935 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22936 }
22937 $SystemRoot = $SystemRoot_Opt;
22938 $SystemRoot=~s/[\/]+\Z//g;
22939 if($SystemRoot) {
22940 $SystemRoot = get_abs_path($SystemRoot);
22941 }
22942 }
22943 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022944
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022945 if($SortDump)
22946 {
22947 $Data::Dumper::Useperl = 1;
22948 $Data::Dumper::Sortkeys = \&dump_sorting;
22949 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022950
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022951 if($TargetLibsPath)
22952 {
22953 if(not -f $TargetLibsPath) {
22954 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22955 }
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022956 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
22957 {
22958 if($OSgroup eq "windows") {
22959 $TargetLibs{lc($Lib)} = 1;
22960 }
22961 else {
22962 $TargetLibs{$Lib} = 1;
22963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022964 }
22965 }
22966 if($TargetHeadersPath)
22967 { # --headers-list
22968 if(not -f $TargetHeadersPath) {
22969 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22970 }
22971 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22972 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022973 $TargetHeaders{1}{get_filename($Header)} = 1;
22974 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022975 }
22976 }
22977 if($TargetHeader)
22978 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022979 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22980 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022981 }
22982 if($TestTool
22983 or $TestDump)
22984 { # --test, --test-dump
22985 detect_default_paths("bin|gcc"); # to compile libs
22986 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022987 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030022988 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022989 exit(0);
22990 }
22991 if($DumpSystem)
22992 { # --dump-system
Andrey Ponomarenko81b09e82016-08-11 20:14:41 +030022993 if(-d $MODULES_DIR."/Targets/"
22994 and -d $MODULES_DIR."/Targets/".$OStarget) {
22995 $TargetSysInfo = $MODULES_DIR."/Targets/".$OStarget;
22996 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022997 if(not $TargetSysInfo) {
22998 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22999 }
23000
23001 if(not -d $TargetSysInfo) {
23002 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
23003 }
23004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023005 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023006 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023007 { # system XML descriptor
23008 if(not -f $DumpSystem) {
23009 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
23010 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030023011
23012 my $SDesc = readFile($DumpSystem);
23013 if(my $RelDir = $RelativeDirectory{1}) {
23014 $SDesc =~ s/{RELPATH}/$RelDir/g;
23015 }
23016
23017 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023018 foreach (@{$Ret->{"Tools"}})
23019 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040023020 push_U($SystemPaths{"bin"}, $_);
23021 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023022 }
23023 if($Ret->{"CrossPrefix"}) {
23024 $CrossPrefix = $Ret->{"CrossPrefix"};
23025 }
23026 }
23027 elsif($SystemRoot_Opt)
23028 { # -sysroot "/" option
23029 # default target: /usr/lib, /usr/include
23030 # search libs: /usr/lib and /lib
23031 if(not -e $SystemRoot."/usr/lib") {
23032 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
23033 }
23034 if(not -e $SystemRoot."/lib") {
23035 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
23036 }
23037 if(not -e $SystemRoot."/usr/include") {
23038 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
23039 }
23040 readSystemDescriptor("
23041 <name>
23042 $DumpSystem
23043 </name>
23044 <headers>
23045 $SystemRoot/usr/include
23046 </headers>
23047 <libs>
23048 $SystemRoot/usr/lib
23049 </libs>
23050 <search_libs>
23051 $SystemRoot/lib
23052 </search_libs>");
23053 }
23054 else {
23055 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
23056 }
23057 detect_default_paths("bin|gcc"); # to check symbols
23058 if($OStarget eq "windows")
23059 { # to run dumpbin.exe
23060 # and undname.exe
23061 check_win32_env();
23062 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023063 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023064 exit(0);
23065 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023067 if($CmpSystems)
23068 { # --cmp-systems
23069 detect_default_paths("bin"); # to extract dumps
23070 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040023071 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023072 exit(0);
23073 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023074
23075 if(not $CountSymbols)
23076 {
23077 if(not $TargetLibraryName) {
23078 exitStatus("Error", "library name is not selected (-l option)");
23079 }
23080 else
23081 { # validate library name
23082 if($TargetLibraryName=~/[\*\/\\]/) {
23083 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
23084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023085 }
23086 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023087
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030023088 if(not $TargetTitle) {
23089 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023090 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023091
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023092 if($SymbolsListPath)
23093 {
23094 if(not -f $SymbolsListPath) {
23095 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
23096 }
23097 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
23098 $SymbolsList{$Interface} = 1;
23099 }
23100 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030023101 if($TypesListPath)
23102 {
23103 if(not -f $TypesListPath) {
23104 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
23105 }
23106 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23107 $TypesList{$Type} = 1;
23108 }
23109 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023110 if($SkipSymbolsListPath)
23111 {
23112 if(not -f $SkipSymbolsListPath) {
23113 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23114 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023115 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23116 {
23117 $SkipSymbols{1}{$Interface} = 1;
23118 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023119 }
23120 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023121 if($SkipTypesListPath)
23122 {
23123 if(not -f $SkipTypesListPath) {
23124 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23125 }
23126 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23127 {
23128 $SkipTypes{1}{$Type} = 1;
23129 $SkipTypes{2}{$Type} = 1;
23130 }
23131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023132 if($SkipHeadersPath)
23133 {
23134 if(not -f $SkipHeadersPath) {
23135 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23136 }
23137 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023138 { # register for both versions
23139 $SkipHeadersList{1}{$Path} = 1;
23140 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023142 my ($CPath, $Type) = classifyPath($Path);
23143 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023144 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023145 }
23146 }
23147 if($ParamNamesPath)
23148 {
23149 if(not -f $ParamNamesPath) {
23150 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23151 }
23152 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23153 {
23154 if($Line=~s/\A(\w+)\;//)
23155 {
23156 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023157 if($Line=~/;(\d+);/)
23158 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023159 while($Line=~s/(\d+);(\w+)//) {
23160 $AddIntParams{$Interface}{$1}=$2;
23161 }
23162 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023163 else
23164 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023165 my $Num = 0;
23166 foreach my $Name (split(/;/, $Line)) {
23167 $AddIntParams{$Interface}{$Num++}=$Name;
23168 }
23169 }
23170 }
23171 }
23172 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023173
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023174 if($AppPath)
23175 {
23176 if(not -f $AppPath) {
23177 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23178 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023179
23180 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023181 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023182 $SymbolsList_App{$Interface} = 1;
23183 }
23184 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023185
23186 if($CountSymbols)
23187 {
23188 if(not -e $CountSymbols) {
23189 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23190 }
23191
23192 read_ABI_Dump(1, $CountSymbols);
23193
23194 foreach my $Id (keys(%{$SymbolInfo{1}}))
23195 {
23196 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23197 if(not $MnglName) {
23198 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23199 }
23200
23201 if(my $SV = $SymVer{1}{$MnglName}) {
23202 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23203 }
23204 else {
23205 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23206 }
23207
23208 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23209 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23210 }
23211 }
23212
23213 my $Count = 0;
23214 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23215 {
23216 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23217 next;
23218 }
23219 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23220 next;
23221 }
23222 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23223 next;
23224 }
23225
23226 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23227 }
23228
23229 printMsg("INFO", $Count);
23230 exit(0);
23231 }
23232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023233 if($DumpAPI)
23234 { # --dump-abi
23235 # make an API dump
23236 create_ABI_Dump();
23237 exit($COMPILE_ERRORS);
23238 }
23239 # default: compare APIs
23240 # -d1 <path>
23241 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023242 compareInit();
23243 if($JoinReport or $DoubleReport)
23244 {
23245 compareAPIs("Binary");
23246 compareAPIs("Source");
23247 }
23248 elsif($BinaryOnly) {
23249 compareAPIs("Binary");
23250 }
23251 elsif($SourceOnly) {
23252 compareAPIs("Source");
23253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023254 exitReport();
23255}
23256
23257scenario();