blob: d710d07b5183a1b04604174c73fbb2b4215a4406 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03003# ABI Compliance Checker (ABICC) 1.99.10
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 Ponomarenko52b2e352015-08-11 22:45:36 +03008# Copyright (C) 2012-2013 ROSA Laboratory
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +03009# Copyright (C) 2013-2015 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 Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040030# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030041# ABI Dumper >= 0.99.9
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040042#
43#
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040044# This program is free software: you can redistribute it and/or modify
45# it under the terms of the GNU General Public License or the GNU Lesser
46# General Public License as published by the Free Software Foundation.
47#
48# This program is distributed in the hope that it will be useful,
49# but WITHOUT ANY WARRANTY; without even the implied warranty of
50# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51# GNU General Public License for more details.
52#
53# You should have received a copy of the GNU General Public License
54# and the GNU Lesser General Public License along with this program.
55# If not, see <http://www.gnu.org/licenses/>.
56###########################################################################
57use Getopt::Long;
58Getopt::Long::Configure ("posix_default", "no_ignore_case");
59use File::Path qw(mkpath rmtree);
60use File::Temp qw(tempdir);
61use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040062use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040063use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040064use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040065use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040066
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030067my $TOOL_VERSION = "1.99.10";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040069my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040070my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071my $OSgroup = get_OSgroup();
72my $ORIG_DIR = cwd();
73my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030074my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040075
76# Internal modules
77my $MODULES_DIR = get_Modules();
78push(@INC, get_dirname($MODULES_DIR));
79# Rules DB
80my %RULES_PATH = (
81 "Binary" => $MODULES_DIR."/RulesBin.xml",
82 "Source" => $MODULES_DIR."/RulesSrc.xml");
83
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030084my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030086$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030087%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030088%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040089$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
90$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
91$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040092$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040093$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030094$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030097$TargetArch, $GccOptions, $TypesListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040098
99my $CmdName = get_filename($0);
100my %OS_LibExt = (
101 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400103 "macos"=>"dylib",
104 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400105 "symbian"=>"dso",
106 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 },
108 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400109 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400111 "symbian"=>"lib",
112 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400113 }
114);
115
116my %OS_Archive = (
117 "windows"=>"zip",
118 "default"=>"tar.gz"
119);
120
121my %ERROR_CODE = (
122 # Compatible verdict
123 "Compatible"=>0,
124 "Success"=>0,
125 # Incompatible verdict
126 "Incompatible"=>1,
127 # Undifferentiated error code
128 "Error"=>2,
129 # System command is not found
130 "Not_Found"=>3,
131 # Cannot access input files
132 "Access_Error"=>4,
133 # Cannot compile header files
134 "Cannot_Compile"=>5,
135 # Header compiled with errors
136 "Compile_Error"=>6,
137 # Invalid input ABI dump
138 "Invalid_Dump"=>7,
139 # Incompatible version of ABI dump
140 "Dump_Version"=>8,
141 # Cannot find a module
142 "Module_Error"=>9,
143 # Empty intersection between
144 # headers and shared objects
145 "Empty_Intersection"=>10,
146 # Empty set of symbols in headers
147 "Empty_Set"=>11
148);
149
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300150my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400151
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400152my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400153A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300154Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400155License: GNU LGPL or GNU GPL
156
157Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400158Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400159
160OLD.xml and NEW.xml are XML-descriptors:
161
162 <version>
163 1.0
164 </version>
165
166 <headers>
167 /path/to/headers/
168 </headers>
169
170 <libs>
171 /path/to/libraries/
172 </libs>
173
174More info: $CmdName --help\n";
175
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400176if($#ARGV==-1)
177{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400178 printMsg("INFO", $ShortUsage);
179 exit(0);
180}
181
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400182GetOptions("h|help!" => \$Help,
183 "i|info!" => \$InfoMsg,
184 "v|version!" => \$ShowVersion,
185 "dumpversion!" => \$DumpVersion,
186# general options
187 "l|lib|library=s" => \$TargetLibraryName,
188 "d1|old|o=s" => \$Descriptor{1}{"Path"},
189 "d2|new|n=s" => \$Descriptor{2}{"Path"},
190 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400191# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400192 "app|application=s" => \$AppPath,
193 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400194 "gcc-path|cross-gcc=s" => \$CrossGcc,
195 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
196 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400197 "sysroot=s" => \$SystemRoot_Opt,
198 "v1|version1|vnum=s" => \$TargetVersion{1},
199 "v2|version2=s" => \$TargetVersion{2},
200 "s|strict!" => \$StrictCompat,
201 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300202 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400203 "skip-symbols=s" => \$SkipSymbolsListPath,
204 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400205 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400206 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400207 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400208 "show-retval!" => \$ShowRetVal,
209 "use-dumps!" => \$UseDumps,
210 "nostdinc!" => \$NoStdInc,
211 "dump-system=s" => \$DumpSystem,
212 "sysinfo=s" => \$TargetSysInfo,
213 "cmp-systems!" => \$CmpSystems,
214 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400215 "ext|extended!" => \$ExtendedCheck,
216 "q|quiet!" => \$Quiet,
217 "stdout!" => \$StdOut,
218 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400219 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400220 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400222 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400223 "binary|bin|abi!" => \$BinaryOnly,
224 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400225 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400226# other options
227 "test!" => \$TestTool,
228 "test-dump!" => \$TestDump,
229 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400230 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400231 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400232 "p|params=s" => \$ParamNamesPath,
233 "relpath1|relpath=s" => \$RelativeDirectory{1},
234 "relpath2=s" => \$RelativeDirectory{2},
235 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400236 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400237 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400238 "bin-report-path=s" => \$BinaryReportPath,
239 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "log-path=s" => \$LoggingPath,
241 "log1-path=s" => \$OutputLogPath{1},
242 "log2-path=s" => \$OutputLogPath{2},
243 "logging-mode=s" => \$LogMode,
244 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300245 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400246 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400247 "extra-info=s" => \$ExtraInfo,
248 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400249 "force!" => \$Force,
250 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400251 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400252 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400253 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400254 "all-affected!" => \$AllAffected,
255 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400256) or ERR_MESSAGE();
257
258sub ERR_MESSAGE()
259{
260 printMsg("INFO", "\n".$ShortUsage);
261 exit($ERROR_CODE{"Error"});
262}
263
264my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
265my $SLIB_TYPE = $LIB_TYPE;
266if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
267{ # show as "shared" library
268 $SLIB_TYPE = "shared";
269}
270my $LIB_EXT = getLIB_EXT($OSgroup);
271my $AR_EXT = getAR_EXT($OSgroup);
272my $BYTE_SIZE = 8;
273my $COMMON_LOG_PATH = "logs/run.log";
274
275my $HelpMessage="
276NAME:
277 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400278 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400279
280DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400281 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400282 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
283 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
284 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
285 and/or source-level compatibility: changes in calling stack, v-table changes,
286 removed symbols, renamed fields, etc. Binary incompatibility may result in
287 crashing or incorrect behavior of applications built with an old version of
288 a library if they run on a new one. Source incompatibility may result in
289 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400290
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400291 The tool is intended for developers of software libraries and maintainers
292 of operating systems who are interested in ensuring backward compatibility,
293 i.e. allow old applications to run or to be recompiled with newer library
294 versions.
295
296 Also the tool can be used by ISVs for checking applications portability to
297 new library versions. Found issues can be taken into account when adapting
298 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400299
300 This tool is free software: you can redistribute it and/or modify it
301 under the terms of the GNU LGPL or GNU GPL.
302
303USAGE:
304 $CmdName [options]
305
306EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400307 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400308
309 OLD.xml and NEW.xml are XML-descriptors:
310
311 <version>
312 1.0
313 </version>
314
315 <headers>
316 /path1/to/header(s)/
317 /path2/to/header(s)/
318 ...
319 </headers>
320
321 <libs>
322 /path1/to/library(ies)/
323 /path2/to/library(ies)/
324 ...
325 </libs>
326
327INFORMATION OPTIONS:
328 -h|-help
329 Print this help.
330
331 -i|-info
332 Print complete info.
333
334 -v|-version
335 Print version information.
336
337 -dumpversion
338 Print the tool version ($TOOL_VERSION) and don't do anything else.
339
340GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400341 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400342 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400343
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400344 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345 Descriptor of 1st (old) library version.
346 It may be one of the following:
347
348 1. XML-descriptor (VERSION.xml file):
349
350 <version>
351 1.0
352 </version>
353
354 <headers>
355 /path1/to/header(s)/
356 /path2/to/header(s)/
357 ...
358 </headers>
359
360 <libs>
361 /path1/to/library(ies)/
362 /path2/to/library(ies)/
363 ...
364 </libs>
365
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300366 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367
368 2. ABI dump generated by -dump option
369 3. Directory with headers and/or $SLIB_TYPE libraries
370 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300372 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400373 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374
375 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400376 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400377
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400378 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379 Descriptor of 2nd (new) library version.
380
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400381 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400382 Create library ABI dump for the input XML descriptor. You can
383 transfer it anywhere and pass instead of the descriptor. Also
384 it can be used for debugging the tool.
385
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300386 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400387
388sub HELP_MESSAGE() {
389 printMsg("INFO", $HelpMessage."
390MORE INFO:
391 $CmdName --info\n");
392}
393
394sub INFO_MESSAGE()
395{
396 printMsg("INFO", "$HelpMessage
397EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400398 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300399 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400400 for portability to the new library version.
401
402 -static-libs
403 Check static libraries instead of the shared ones. The <libs> section
404 of the XML-descriptor should point to static libraries location.
405
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400406 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 Path to the cross GCC compiler to use instead of the usual (host) GCC.
408
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400409 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 GCC toolchain prefix.
411
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400412 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400413 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400414 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400416 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200418 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
420 In general case you should specify it in the XML-descriptor:
421 <version>
422 VERSION
423 </version>
424
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400425 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400426 Specify 2nd library version outside the descriptor.
427
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400428 -vnum NUM
429 Specify the library version in the generated ABI dump. The <version> section
430 of the input XML descriptor will be overwritten in this case.
431
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432 -s|-strict
433 Treat all compatibility warnings as problems. Add a number of \"Low\"
434 severity problems to the return value of the tool.
435
436 -headers-only
437 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
438 provide a low quality compatibility report with false positives and
439 without detecting of added/removed symbols.
440
441 Alternatively you can write \"none\" word to the <libs> section
442 in the XML-descriptor:
443 <libs>
444 none
445 </libs>
446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447 -show-retval
448 Show the symbol's return type in the report.
449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400450 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300451 This option allows to specify a file with a list of symbols (mangled
452 names in C++) that should be checked. Other symbols will not be checked.
453
454 -types-list PATH
455 This option allows to specify a file with a list of types that should
456 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400457
458 -skip-symbols PATH
459 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400460
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400461 -headers-list PATH
462 The file with a list of headers, that should be checked/dumped.
463
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400464 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400465 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400466
467 -header NAME
468 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400469
470 -use-dumps
471 Make dumps for two versions of a library and compare dumps. This should
472 increase the performance of the tool and decrease the system memory usage.
473
474 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400475 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400476
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400477 -dump-system NAME -sysroot DIR
478 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400479 create XML descriptors and make ABI dumps for each library. The result
480 set of ABI dumps can be compared (--cmp-systems) with the other one
481 created for other version of operating system in order to check them for
482 compatibility. Do not forget to specify -cross-gcc option if your target
483 system requires some specific version of GCC compiler (different from
484 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400485 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400486
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400487 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400488 The same as the previous option but takes an XML descriptor of the target
489 system as input, where you should describe it:
490
491 /* Primary sections */
492
493 <name>
494 /* Name of the system */
495 </name>
496
497 <headers>
498 /* The list of paths to header files and/or
499 directories with header files, one per line */
500 </headers>
501
502 <libs>
503 /* The list of paths to shared libraries and/or
504 directories with shared libraries, one per line */
505 </libs>
506
507 /* Optional sections */
508
509 <search_headers>
510 /* List of directories to be searched
511 for header files to automatically
512 generate include paths, one per line */
513 </search_headers>
514
515 <search_libs>
516 /* List of directories to be searched
517 for shared libraries to resolve
518 dependencies, one per line */
519 </search_libs>
520
521 <tools>
522 /* List of directories with tools used
523 for analysis (GCC toolchain), one per line */
524 </tools>
525
526 <cross_prefix>
527 /* GCC toolchain prefix.
528 Examples:
529 arm-linux-gnueabi
530 arm-none-symbianelf */
531 </cross_prefix>
532
533 <gcc_options>
534 /* Additional GCC options, one per line */
535 </gcc_options>
536
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400537 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300538 This option should be used with -dump-system option to dump
539 ABI of operating systems and configure the dumping process.
540 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400541 modules/Targets/{unix, symbian, windows}
542
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400543 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400544 Compare two system ABI dumps. Create compatibility reports for each
545 library and the common HTML report including the summary of test
546 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400547 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400548
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400549 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400550 The file with a list of libraries, that should be dumped by
551 the -dump-system option or should be checked by the -cmp-systems option.
552
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553 -ext|-extended
554 If your library A is supposed to be used by other library B and you
555 want to control the ABI of B, then you should enable this option. The
556 tool will check for changes in all data types, even if they are not
557 used by any function in the library A. Such data types are not part
558 of the A library ABI, but may be a part of the ABI of the B library.
559
560 The short scheme is:
561 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
562
563 -q|-quiet
564 Print all messages to the file instead of stdout and stderr.
565 Default path (can be changed by -log-path option):
566 $COMMON_LOG_PATH
567
568 -stdout
569 Print analysis results (compatibility reports and ABI dumps) to stdout
570 instead of creating a file. This would allow piping data to other programs.
571
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400572 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400573 Change format of compatibility report.
574 Formats:
575 htm - HTML format (default)
576 xml - XML format
577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400579 Change format of ABI dump.
580 Formats:
581 perl - Data::Dumper format (default)
582 xml - XML format
583
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400584 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400585 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400586
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400587 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400588 Set library language (C or C++). You can use this option if the tool
589 cannot auto-detect a language. This option may be useful for checking
590 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400591
592 -arch ARCH
593 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
594 ect.). The option is useful if the tool cannot detect correct architecture
595 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400597 -binary|-bin|-abi
598 Show \"Binary\" compatibility problems only.
599 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400600 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400601
602 -source|-src|-api
603 Show \"Source\" compatibility problems only.
604 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400605 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400606
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400607 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400608 The maximum number of affected symbols listed under the description
609 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400611OTHER OPTIONS:
612 -test
613 Run internal tests. Create two binary incompatible versions of a sample
614 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300615 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400616
617 -test-dump
618 Test ability to create, read and compare ABI dumps.
619
620 -debug
621 Debugging mode. Print debug info on the screen. Save intermediate
622 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400623 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400624
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400625 Also consider using --dump option for debugging the tool.
626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400627 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400628 If your header files are written in C language and can be compiled
629 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
630 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400631
632 -cpp-incompatible
633 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400634
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400636 Path to file with the function parameter names. It can be used
637 for improving report view if the library header files have no
638 parameter names. File format:
639
640 func1;param1;param2;param3 ...
641 func2;param1;param2;param3 ...
642 ...
643
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400644 -relpath PATH
645 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400646 for dumping the library ABI (see -dump option).
647
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400648 -relpath1 PATH
649 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400650
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400651 -relpath2 PATH
652 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400654 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400655 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400658
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400659 -sort
660 Enable sorting of data in ABI dumps.
661
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400663 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400664 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400665 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400668 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400671
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400672 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400673 Path to \"Source\" compatibility report.
674 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400678 Log path for all messages.
679 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400682 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683 Log path for 1st version of a library.
684 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400688 Log path for 2nd version of a library.
689 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693 Change logging mode.
694 Modes:
695 w - overwrite old logs (default)
696 a - append old logs
697 n - do not write any logs
698
699 -list-affected
700 Generate file with the list of incompatible
701 symbols beside the HTML compatibility report.
702 Use 'c++filt \@file' command from GNU binutils
703 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400704 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400705 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400706 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400707
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709 The component name in the title and summary of the HTML report.
710 Default:
711 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300712
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300713 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716
717 -extra-info DIR
718 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400719
720 -extra-dump
721 Create extended ABI dump containing all symbols
722 from the translation unit.
723
724 -force
725 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400726
727 -tolerance LEVEL
728 Apply a set of heuristics to successfully compile input
729 header files. You can enable several tolerance levels by
730 joining them into one string (e.g. 13, 124, etc.).
731 Levels:
732 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
733 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
734 3 - skip headers that iclude non-Linux headers
735 4 - skip headers included by others
736
737 -tolerant
738 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400739
740 -check
741 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400742
743 -quick
744 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400745
746 -skip-internal PATTERN
747 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400749REPORT:
750 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752
753 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400754 logs/LIB_NAME/V1/log.txt
755 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400756
757EXIT CODES:
758 0 - Compatible. The tool has run without any errors.
759 non-zero - Incompatible or the tool has run with errors.
760
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400761MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300762 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400763}
764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400765my %Operator_Indication = (
766 "not" => "~",
767 "assign" => "=",
768 "andassign" => "&=",
769 "orassign" => "|=",
770 "xorassign" => "^=",
771 "or" => "|",
772 "xor" => "^",
773 "addr" => "&",
774 "and" => "&",
775 "lnot" => "!",
776 "eq" => "==",
777 "ne" => "!=",
778 "lt" => "<",
779 "lshift" => "<<",
780 "lshiftassign" => "<<=",
781 "rshiftassign" => ">>=",
782 "call" => "()",
783 "mod" => "%",
784 "modassign" => "%=",
785 "subs" => "[]",
786 "land" => "&&",
787 "lor" => "||",
788 "rshift" => ">>",
789 "ref" => "->",
790 "le" => "<=",
791 "deref" => "*",
792 "mult" => "*",
793 "preinc" => "++",
794 "delete" => " delete",
795 "vecnew" => " new[]",
796 "vecdelete" => " delete[]",
797 "predec" => "--",
798 "postinc" => "++",
799 "postdec" => "--",
800 "plusassign" => "+=",
801 "plus" => "+",
802 "minus" => "-",
803 "minusassign" => "-=",
804 "gt" => ">",
805 "ge" => ">=",
806 "new" => " new",
807 "multassign" => "*=",
808 "divassign" => "/=",
809 "div" => "/",
810 "neg" => "-",
811 "pos" => "+",
812 "memref" => "->*",
813 "compound" => "," );
814
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400815my %UnknownOperator;
816
817my %NodeType= (
818 "array_type" => "Array",
819 "binfo" => "Other",
820 "boolean_type" => "Intrinsic",
821 "complex_type" => "Intrinsic",
822 "const_decl" => "Other",
823 "enumeral_type" => "Enum",
824 "field_decl" => "Other",
825 "function_decl" => "Other",
826 "function_type" => "FunctionType",
827 "identifier_node" => "Other",
828 "integer_cst" => "Other",
829 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400830 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400831 "method_type" => "MethodType",
832 "namespace_decl" => "Other",
833 "parm_decl" => "Other",
834 "pointer_type" => "Pointer",
835 "real_cst" => "Other",
836 "real_type" => "Intrinsic",
837 "record_type" => "Struct",
838 "reference_type" => "Ref",
839 "string_cst" => "Other",
840 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400841 "template_type_parm" => "TemplateParam",
842 "typename_type" => "TypeName",
843 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400844 "tree_list" => "Other",
845 "tree_vec" => "Other",
846 "type_decl" => "Other",
847 "union_type" => "Union",
848 "var_decl" => "Other",
849 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400850 "nop_expr" => "Other", #
851 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400852 "offset_type" => "Other" );
853
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400854my %CppKeywords_C = map {$_=>1} (
855 # C++ 2003 keywords
856 "public",
857 "protected",
858 "private",
859 "default",
860 "template",
861 "new",
862 #"asm",
863 "dynamic_cast",
864 "auto",
865 "try",
866 "namespace",
867 "typename",
868 "using",
869 "reinterpret_cast",
870 "friend",
871 "class",
872 "virtual",
873 "const_cast",
874 "mutable",
875 "static_cast",
876 "export",
877 # C++0x keywords
878 "noexcept",
879 "nullptr",
880 "constexpr",
881 "static_assert",
882 "explicit",
883 # cannot be used as a macro name
884 # as it is an operator in C++
885 "and",
886 #"and_eq",
887 "not",
888 #"not_eq",
889 "or"
890 #"or_eq",
891 #"bitand",
892 #"bitor",
893 #"xor",
894 #"xor_eq",
895 #"compl"
896);
897
898my %CppKeywords_F = map {$_=>1} (
899 "delete",
900 "catch",
901 "alignof",
902 "thread_local",
903 "decltype",
904 "typeid"
905);
906
907my %CppKeywords_O = map {$_=>1} (
908 "bool",
909 "register",
910 "inline",
911 "operator"
912);
913
914my %CppKeywords_A = map {$_=>1} (
915 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400916 "throw",
917 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400918);
919
920foreach (keys(%CppKeywords_C),
921keys(%CppKeywords_F),
922keys(%CppKeywords_O)) {
923 $CppKeywords_A{$_}=1;
924}
925
926# Header file extensions as described by gcc
927my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
928
929my %IntrinsicMangling = (
930 "void" => "v",
931 "bool" => "b",
932 "wchar_t" => "w",
933 "char" => "c",
934 "signed char" => "a",
935 "unsigned char" => "h",
936 "short" => "s",
937 "unsigned short" => "t",
938 "int" => "i",
939 "unsigned int" => "j",
940 "long" => "l",
941 "unsigned long" => "m",
942 "long long" => "x",
943 "__int64" => "x",
944 "unsigned long long" => "y",
945 "__int128" => "n",
946 "unsigned __int128" => "o",
947 "float" => "f",
948 "double" => "d",
949 "long double" => "e",
950 "__float80" => "e",
951 "__float128" => "g",
952 "..." => "z"
953);
954
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400955my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400957my %StdcxxMangling = (
958 "3std"=>"St",
959 "3std9allocator"=>"Sa",
960 "3std12basic_string"=>"Sb",
961 "3std12basic_stringIcE"=>"Ss",
962 "3std13basic_istreamIcE"=>"Si",
963 "3std13basic_ostreamIcE"=>"So",
964 "3std14basic_iostreamIcE"=>"Sd"
965);
966
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400967my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400968my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
969
970my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400971my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400973my %ConstantSuffix = (
974 "unsigned int"=>"u",
975 "long"=>"l",
976 "unsigned long"=>"ul",
977 "long long"=>"ll",
978 "unsigned long long"=>"ull"
979);
980
981my %ConstantSuffixR =
982reverse(%ConstantSuffix);
983
984my %OperatorMangling = (
985 "~" => "co",
986 "=" => "aS",
987 "|" => "or",
988 "^" => "eo",
989 "&" => "an",#ad (addr)
990 "==" => "eq",
991 "!" => "nt",
992 "!=" => "ne",
993 "<" => "lt",
994 "<=" => "le",
995 "<<" => "ls",
996 "<<=" => "lS",
997 ">" => "gt",
998 ">=" => "ge",
999 ">>" => "rs",
1000 ">>=" => "rS",
1001 "()" => "cl",
1002 "%" => "rm",
1003 "[]" => "ix",
1004 "&&" => "aa",
1005 "||" => "oo",
1006 "*" => "ml",#de (deref)
1007 "++" => "pp",#
1008 "--" => "mm",#
1009 "new" => "nw",
1010 "delete" => "dl",
1011 "new[]" => "na",
1012 "delete[]" => "da",
1013 "+=" => "pL",
1014 "+" => "pl",#ps (pos)
1015 "-" => "mi",#ng (neg)
1016 "-=" => "mI",
1017 "*=" => "mL",
1018 "/=" => "dV",
1019 "&=" => "aN",
1020 "|=" => "oR",
1021 "%=" => "rM",
1022 "^=" => "eO",
1023 "/" => "dv",
1024 "->*" => "pm",
1025 "->" => "pt",#rf (ref)
1026 "," => "cm",
1027 "?" => "qu",
1028 "." => "dt",
1029 "sizeof"=> "sz"#st
1030);
1031
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001032my %Intrinsic_Keywords = map {$_=>1} (
1033 "true",
1034 "false",
1035 "_Bool",
1036 "_Complex",
1037 "const",
1038 "int",
1039 "long",
1040 "void",
1041 "short",
1042 "float",
1043 "volatile",
1044 "restrict",
1045 "unsigned",
1046 "signed",
1047 "char",
1048 "double",
1049 "class",
1050 "struct",
1051 "union",
1052 "enum"
1053);
1054
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001055my %GlibcHeader = map {$_=>1} (
1056 "aliases.h",
1057 "argp.h",
1058 "argz.h",
1059 "assert.h",
1060 "cpio.h",
1061 "ctype.h",
1062 "dirent.h",
1063 "envz.h",
1064 "errno.h",
1065 "error.h",
1066 "execinfo.h",
1067 "fcntl.h",
1068 "fstab.h",
1069 "ftw.h",
1070 "glob.h",
1071 "grp.h",
1072 "iconv.h",
1073 "ifaddrs.h",
1074 "inttypes.h",
1075 "langinfo.h",
1076 "limits.h",
1077 "link.h",
1078 "locale.h",
1079 "malloc.h",
1080 "math.h",
1081 "mntent.h",
1082 "monetary.h",
1083 "nl_types.h",
1084 "obstack.h",
1085 "printf.h",
1086 "pwd.h",
1087 "regex.h",
1088 "sched.h",
1089 "search.h",
1090 "setjmp.h",
1091 "shadow.h",
1092 "signal.h",
1093 "spawn.h",
1094 "stdarg.h",
1095 "stdint.h",
1096 "stdio.h",
1097 "stdlib.h",
1098 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001099 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001100 "tar.h",
1101 "termios.h",
1102 "time.h",
1103 "ulimit.h",
1104 "unistd.h",
1105 "utime.h",
1106 "wchar.h",
1107 "wctype.h",
1108 "wordexp.h" );
1109
1110my %GlibcDir = map {$_=>1} (
1111 "arpa",
1112 "bits",
1113 "gnu",
1114 "netinet",
1115 "net",
1116 "nfs",
1117 "rpc",
1118 "sys",
1119 "linux" );
1120
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001121my %WinHeaders = map {$_=>1} (
1122 "dos.h",
1123 "process.h",
1124 "winsock.h",
1125 "config-win.h",
1126 "mem.h",
1127 "windows.h",
1128 "winsock2.h",
1129 "crtdbg.h",
1130 "ws2tcpip.h"
1131);
1132
1133my %ObsoleteHeaders = map {$_=>1} (
1134 "iostream.h",
1135 "fstream.h"
1136);
1137
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001138my %AlienHeaders = map {$_=>1} (
1139 # Solaris
1140 "thread.h",
1141 "sys/atomic.h",
1142 # HPUX
1143 "sys/stream.h",
1144 # Symbian
1145 "AknDoc.h",
1146 # Atari ST
1147 "ext.h",
1148 "tos.h",
1149 # MS-DOS
1150 "alloc.h",
1151 # Sparc
1152 "sys/atomic.h"
1153);
1154
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001155my %ConfHeaders = map {$_=>1} (
1156 "atomic",
1157 "conf.h",
1158 "config.h",
1159 "configure.h",
1160 "build.h",
1161 "setup.h"
1162);
1163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001164my %LocalIncludes = map {$_=>1} (
1165 "/usr/local/include",
1166 "/usr/local" );
1167
1168my %OS_AddPath=(
1169# These paths are needed if the tool cannot detect them automatically
1170 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001171 "include"=>[
1172 "/Library",
1173 "/Developer/usr/include"
1174 ],
1175 "lib"=>[
1176 "/Library",
1177 "/Developer/usr/lib"
1178 ],
1179 "bin"=>[
1180 "/Developer/usr/bin"
1181 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001182 },
1183 "beos"=>{
1184 # Haiku has GCC 2.95.3 by default
1185 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001186 "include"=>[
1187 "/boot/common",
1188 "/boot/develop"
1189 ],
1190 "lib"=>[
1191 "/boot/common/lib",
1192 "/boot/system/lib",
1193 "/boot/apps"
1194 ],
1195 "bin"=>[
1196 "/boot/common/bin",
1197 "/boot/system/bin",
1198 "/boot/develop/abi"
1199 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001201);
1202
1203my %Slash_Type=(
1204 "default"=>"/",
1205 "windows"=>"\\"
1206);
1207
1208my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1209
1210# Global Variables
1211my %COMMON_LANGUAGE=(
1212 1 => "C",
1213 2 => "C" );
1214
1215my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001216my $MAX_CPPFILT_FILE_SIZE = 50000;
1217my $CPPFILT_SUPPORT_FILE;
1218
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001219my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001221my $STDCXX_TESTING = 0;
1222my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001223my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001224
1225my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001226
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001227my $TargetComponent;
1228
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001229my $CheckUndefined = 0;
1230
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001231# Set Target Component Name
1232if($TargetComponent_Opt) {
1233 $TargetComponent = lc($TargetComponent_Opt);
1234}
1235else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001236{ # default: library
1237 # other components: header, system, ...
1238 $TargetComponent = "library";
1239}
1240
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001241my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001243my $SystemRoot;
1244
1245my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001246my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001247my %LOG_PATH;
1248my %DEBUG_PATH;
1249my %Cache;
1250my %LibInfo;
1251my $COMPILE_ERRORS = 0;
1252my %CompilerOptions;
1253my %CheckedDyLib;
1254my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1255
1256# Constants (#defines)
1257my %Constants;
1258my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001259my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001260
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001261# Extra Info
1262my %SymbolHeader;
1263my %KnownLibs;
1264
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001265# Templates
1266my %TemplateInstance;
1267my %BasicTemplate;
1268my %TemplateArg;
1269my %TemplateDecl;
1270my %TemplateMap;
1271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001272# Types
1273my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001274my %SkipTypes = (
1275 "1"=>{},
1276 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001277my %CheckedTypes;
1278my %TName_Tid;
1279my %EnumMembName_Id;
1280my %NestedNameSpaces = (
1281 "1"=>{},
1282 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001283my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001284my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001285my %ClassVTable;
1286my %ClassVTable_Content;
1287my %VTableClass;
1288my %AllocableClass;
1289my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001290my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001291my %Class_SubClasses;
1292my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001293my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001294my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001295
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001296my %CheckedTypeInfo;
1297
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298# Typedefs
1299my %Typedef_BaseName;
1300my %Typedef_Tr;
1301my %Typedef_Eq;
1302my %StdCxxTypedef;
1303my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001304my %MissedBase;
1305my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001306my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307
1308# Symbols
1309my %SymbolInfo;
1310my %tr_name;
1311my %mangled_name_gcc;
1312my %mangled_name;
1313my %SkipSymbols = (
1314 "1"=>{},
1315 "2"=>{} );
1316my %SkipNameSpaces = (
1317 "1"=>{},
1318 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001319my %AddNameSpaces = (
1320 "1"=>{},
1321 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001322my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001323my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001324my %SymbolsList_App;
1325my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001326my %Symbol_Library = (
1327 "1"=>{},
1328 "2"=>{} );
1329my %Library_Symbol = (
1330 "1"=>{},
1331 "2"=>{} );
1332my %DepSymbol_Library = (
1333 "1"=>{},
1334 "2"=>{} );
1335my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336 "1"=>{},
1337 "2"=>{} );
1338my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001339my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001340my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001341my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001342my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001343my %Library_Needed= (
1344 "1"=>{},
1345 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001346
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001347# Extra Info
1348my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001349my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001352my %Include_Preamble = (
1353 "1"=>[],
1354 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001356my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001357my %HeaderName_Paths;
1358my %Header_Dependency;
1359my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001360my %Include_Paths = (
1361 "1"=>[],
1362 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001363my %INC_PATH_AUTODETECT = (
1364 "1"=>1,
1365 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001366my %Add_Include_Paths = (
1367 "1"=>[],
1368 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369my %Skip_Include_Paths;
1370my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371my %Header_ErrorRedirect;
1372my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001373my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374my %Header_ShouldNotBeUsed;
1375my %RecursiveIncludes;
1376my %Header_Include_Prefix;
1377my %SkipHeaders;
1378my %SkipHeadersList=(
1379 "1"=>{},
1380 "2"=>{} );
1381my %SkipLibs;
1382my %Include_Order;
1383my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001384my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001385my %TUnit_Funcs;
1386my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001388my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001389 "1"=>0,
1390 "2"=>0 );
1391my %AutoPreambleMode = (
1392 "1"=>0,
1393 "2"=>0 );
1394my %MinGWMode = (
1395 "1"=>0,
1396 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001397my %Cpp0xMode = (
1398 "1"=>0,
1399 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400
1401# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001402my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001403my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001404my %RegisteredSONAMEs;
1405my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001406
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001407my %CheckedArch;
1408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409# System Objects
1410my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001411my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001412my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413
1414# System Headers
1415my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001416my @DefaultCppPaths;
1417my @DefaultGccPaths;
1418my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001419my %DefaultCppHeader;
1420my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001421my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422
1423# Merging
1424my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001425my $Version;
1426my %AddedInt;
1427my %RemovedInt;
1428my %AddedInt_Virt;
1429my %RemovedInt_Virt;
1430my %VirtualReplacement;
1431my %ChangedTypedef;
1432my %CompatRules;
1433my %IncompleteRules;
1434my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001435my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001436my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001437my %ReturnedClass;
1438my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001439my %SourceAlternative;
1440my %SourceAlternative_B;
1441my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001442my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001443
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001444# Calling Conventions
1445my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001446 1=>{ "R"=>0, "P"=>0 },
1447 2=>{ "R"=>0, "P"=>0 }
1448);
1449
1450# ABI Dump
1451my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001452
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001453# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454my %TargetLibs;
1455my %TargetHeaders;
1456
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001457# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001458my $OStarget = $OSgroup;
1459my %TargetTools;
1460
1461# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001462my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001463
1464# Recursion locks
1465my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001466my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001467my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001468my @RecurInclude;
1469my @RecurConstant;
1470
1471# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001472my %SystemPaths = (
1473 "include"=>[],
1474 "lib"=>[],
1475 "bin"=>[]
1476);
1477my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478my $GCC_PATH;
1479
1480# Symbols versioning
1481my %SymVer = (
1482 "1"=>{},
1483 "2"=>{} );
1484
1485# Problem descriptions
1486my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001487my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001488my %TotalAffected;
1489
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001490# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my $ContentID = 1;
1492my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1493my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1494my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1495my $ContentSpanEnd = "</span>\n";
1496my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1497my $ContentDivEnd = "</div>\n";
1498my $Content_Counter = 0;
1499
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001500# Modes
1501my $JoinReport = 1;
1502my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001503
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001504my %Severity_Val=(
1505 "High"=>3,
1506 "Medium"=>2,
1507 "Low"=>1,
1508 "Safe"=>-1
1509);
1510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001511sub get_Modules()
1512{
1513 my $TOOL_DIR = get_dirname($0);
1514 if(not $TOOL_DIR)
1515 { # patch for MS Windows
1516 $TOOL_DIR = ".";
1517 }
1518 my @SEARCH_DIRS = (
1519 # tool's directory
1520 abs_path($TOOL_DIR),
1521 # relative path to modules
1522 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001523 # install path
1524 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525 );
1526 foreach my $DIR (@SEARCH_DIRS)
1527 {
1528 if(not is_abs($DIR))
1529 { # relative path
1530 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1531 }
1532 if(-d $DIR."/modules") {
1533 return $DIR."/modules";
1534 }
1535 }
1536 exitStatus("Module_Error", "can't find modules");
1537}
1538
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001539my %LoadedModules = ();
1540
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001541sub loadModule($)
1542{
1543 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001544 if(defined $LoadedModules{$Name}) {
1545 return;
1546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001547 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1548 if(not -f $Path) {
1549 exitStatus("Module_Error", "can't access \'$Path\'");
1550 }
1551 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001552 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001553}
1554
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001555sub readModule($$)
1556{
1557 my ($Module, $Name) = @_;
1558 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1559 if(not -f $Path) {
1560 exitStatus("Module_Error", "can't access \'$Path\'");
1561 }
1562 return readFile($Path);
1563}
1564
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001565sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001566{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001567 my $Number = $_[0];
1568 if(not $Number) {
1569 $Number = 1;
1570 }
1571 else {
1572 $Number = int($Number)+1;
1573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001574 if($Number>3) {
1575 return $Number."th";
1576 }
1577 elsif($Number==1) {
1578 return "1st";
1579 }
1580 elsif($Number==2) {
1581 return "2nd";
1582 }
1583 elsif($Number==3) {
1584 return "3rd";
1585 }
1586 else {
1587 return $Number;
1588 }
1589}
1590
1591sub search_Tools($)
1592{
1593 my $Name = $_[0];
1594 return "" if(not $Name);
1595 if(my @Paths = keys(%TargetTools))
1596 {
1597 foreach my $Path (@Paths)
1598 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001599 if(-f join_P($Path, $Name)) {
1600 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001601 }
1602 if($CrossPrefix)
1603 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001604 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001605 if(-f $Candidate) {
1606 return $Candidate;
1607 }
1608 }
1609 }
1610 }
1611 else {
1612 return "";
1613 }
1614}
1615
1616sub synch_Cmd($)
1617{
1618 my $Name = $_[0];
1619 if(not $GCC_PATH)
1620 { # GCC was not found yet
1621 return "";
1622 }
1623 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001624 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001625 return $Candidate;
1626 }
1627 return "";
1628}
1629
1630sub get_CmdPath($)
1631{
1632 my $Name = $_[0];
1633 return "" if(not $Name);
1634 if(defined $Cache{"get_CmdPath"}{$Name}) {
1635 return $Cache{"get_CmdPath"}{$Name};
1636 }
1637 my %BinUtils = map {$_=>1} (
1638 "c++filt",
1639 "objdump",
1640 "readelf"
1641 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001642 if($BinUtils{$Name} and $GCC_PATH)
1643 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001644 if(my $Dir = get_dirname($GCC_PATH)) {
1645 $TargetTools{$Dir}=1;
1646 }
1647 }
1648 my $Path = search_Tools($Name);
1649 if(not $Path and $OSgroup eq "windows") {
1650 $Path = search_Tools($Name.".exe");
1651 }
1652 if(not $Path and $BinUtils{$Name})
1653 {
1654 if($CrossPrefix)
1655 { # user-defined prefix
1656 $Path = search_Cmd($CrossPrefix."-".$Name);
1657 }
1658 }
1659 if(not $Path and $BinUtils{$Name})
1660 {
1661 if(my $Candidate = synch_Cmd($Name))
1662 { # synch with GCC
1663 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001664 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001665 if(-f $Candidate) {
1666 $Path = $Candidate;
1667 }
1668 }
1669 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001670 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001671 $Path = $Candidate;
1672 }
1673 }
1674 }
1675 if(not $Path) {
1676 $Path = search_Cmd($Name);
1677 }
1678 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001679 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001680 $Path=search_Cmd($Name.".exe");
1681 }
1682 if($Path=~/\s/) {
1683 $Path = "\"".$Path."\"";
1684 }
1685 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1686}
1687
1688sub search_Cmd($)
1689{
1690 my $Name = $_[0];
1691 return "" if(not $Name);
1692 if(defined $Cache{"search_Cmd"}{$Name}) {
1693 return $Cache{"search_Cmd"}{$Name};
1694 }
1695 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1696 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1697 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001698 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001699 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001700 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001701 if(-f $CmdPath)
1702 {
1703 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001704 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001705 }
1706 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1707 }
1708 }
1709 return ($Cache{"search_Cmd"}{$Name} = "");
1710}
1711
1712sub get_CmdPath_Default($)
1713{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001714 return "" if(not $_[0]);
1715 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1716 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001718 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1719}
1720
1721sub get_CmdPath_Default_I($)
1722{ # search in PATH
1723 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001724 if($Name=~/find/)
1725 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001726 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001727 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001728 }
1729 }
1730 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001731 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001732 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001733 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001734 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001735 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 if($OSgroup eq "windows")
1737 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001738 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001739 return $Name;
1740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001742 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001743 {
1744 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001745 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 }
1747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001748 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001749}
1750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001751sub classifyPath($)
1752{
1753 my $Path = $_[0];
1754 if($Path=~/[\*\[]/)
1755 { # wildcard
1756 $Path=~s/\*/.*/g;
1757 $Path=~s/\\/\\\\/g;
1758 return ($Path, "Pattern");
1759 }
1760 elsif($Path=~/[\/\\]/)
1761 { # directory or relative path
1762 return (path_format($Path, $OSgroup), "Path");
1763 }
1764 else {
1765 return ($Path, "Name");
1766 }
1767}
1768
1769sub readDescriptor($$)
1770{
1771 my ($LibVersion, $Content) = @_;
1772 return if(not $LibVersion);
1773 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1774 if(not $Content) {
1775 exitStatus("Error", "$DName is empty");
1776 }
1777 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001778 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001779 }
1780 $Content=~s/\/\*(.|\n)+?\*\///g;
1781 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001783 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1784 if($TargetVersion{$LibVersion}) {
1785 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1786 }
1787 if(not $Descriptor{$LibVersion}{"Version"}) {
1788 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1789 }
1790 if($Content=~/{RELPATH}/)
1791 {
1792 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1793 $Content =~ s/{RELPATH}/$RelDir/g;
1794 }
1795 else
1796 {
1797 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1798 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1799 }
1800 }
1801
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001802 my $DHeaders = parseTag(\$Content, "headers");
1803 if(not $DHeaders) {
1804 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1805 }
1806 elsif(lc($DHeaders) ne "none")
1807 { # append the descriptor headers list
1808 if($Descriptor{$LibVersion}{"Headers"})
1809 { # multiple descriptors
1810 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001811 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001812 else {
1813 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1814 }
1815 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1816 {
1817 if(not -e $Path) {
1818 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819 }
1820 }
1821 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001823 if(not $CheckHeadersOnly_Opt)
1824 {
1825 my $DObjects = parseTag(\$Content, "libs");
1826 if(not $DObjects) {
1827 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1828 }
1829 elsif(lc($DObjects) ne "none")
1830 { # append the descriptor libraries list
1831 if($Descriptor{$LibVersion}{"Libs"})
1832 { # multiple descriptors
1833 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1834 }
1835 else {
1836 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1837 }
1838 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1839 {
1840 if(not -e $Path) {
1841 exitStatus("Access_Error", "can't access \'$Path\'");
1842 }
1843 }
1844 }
1845 }
1846 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1847 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001848 if(not -d $Path) {
1849 exitStatus("Access_Error", "can't access directory \'$Path\'");
1850 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001851 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001852 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001853 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001854 }
1855 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1856 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001857 if(not -d $Path) {
1858 exitStatus("Access_Error", "can't access directory \'$Path\'");
1859 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001860 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001861 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001862 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001863 }
1864 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1865 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001866 if(not -d $Path) {
1867 exitStatus("Access_Error", "can't access directory \'$Path\'");
1868 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001869 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001870 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001871 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001872 $TargetTools{$Path}=1;
1873 }
1874 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1875 $CrossPrefix = $Prefix;
1876 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001877 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001878 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1879 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001880 if(not -d $Path) {
1881 exitStatus("Access_Error", "can't access directory \'$Path\'");
1882 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001883 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001884 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001885 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001886 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001887 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001888 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1889 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 if(not -d $Path) {
1891 exitStatus("Access_Error", "can't access directory \'$Path\'");
1892 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001893 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001895 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 }
1897 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001898 { # skip some auto-generated include paths
1899 if(not is_abs($Path))
1900 {
1901 if(my $P = abs_path($Path)) {
1902 $Path = $P;
1903 }
1904 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001905 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 }
1907 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001908 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 my ($CPath, $Type) = classifyPath($Path);
1910 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
1912 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001913 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1914 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001915 if($Option!~/\A\-(Wl|l|L)/)
1916 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001917 $CompilerOptions{$LibVersion} .= " ".$Option;
1918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 }
1920 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1921 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1922 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001923 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001924 my ($CPath, $Type) = classifyPath($Path);
1925 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 }
1927 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1928 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1929 {
1930 my ($CPath, $Type) = classifyPath($Path);
1931 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1932 }
1933 if(my $DDefines = parseTag(\$Content, "defines"))
1934 {
1935 if($Descriptor{$LibVersion}{"Defines"})
1936 { # multiple descriptors
1937 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1938 }
1939 else {
1940 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1941 }
1942 }
1943 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1944 {
1945 if($Order=~/\A(.+):(.+)\Z/) {
1946 $Include_Order{$LibVersion}{$1} = $2;
1947 }
1948 }
1949 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1950 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001951 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1953 }
1954 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1955 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001956 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001957 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1958 }
1959 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1960 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1961 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001962 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1963 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001965 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1966 $SkipConstants{$LibVersion}{$Constant} = 1;
1967 }
1968 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1969 {
1970 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001971 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1973 }
1974 else {
1975 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1976 }
1977 }
1978}
1979
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001980sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001981{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001982 my $CodeRef = shift(@_);
1983 my $Tag = shift(@_);
1984 if(not $Tag or not $CodeRef) {
1985 return undef;
1986 }
1987 my $Sp = 0;
1988 if(@_) {
1989 $Sp = shift(@_);
1990 }
1991 my $Start = index(${$CodeRef}, "<$Tag>");
1992 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001994 my $End = index(${$CodeRef}, "</$Tag>");
1995 if($End!=-1)
1996 {
1997 my $TS = length($Tag)+3;
1998 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
1999 substr($Content, 0, $TS-1, ""); # cut start tag
2000 substr($Content, -$TS, $TS, ""); # cut end tag
2001 if(not $Sp)
2002 {
2003 $Content=~s/\A\s+//g;
2004 $Content=~s/\s+\Z//g;
2005 }
2006 if(substr($Content, 0, 1) ne "<") {
2007 $Content = xmlSpecChars_R($Content);
2008 }
2009 return $Content;
2010 }
2011 }
2012 return undef;
2013}
2014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002015sub getInfo($)
2016{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002017 my $DumpPath = $_[0];
2018 return if(not $DumpPath or not -f $DumpPath);
2019
2020 readTUDump($DumpPath);
2021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002022 # processing info
2023 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002024
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002025 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002026 setAnonTypedef_All();
2027 }
2028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 getTypeInfo_All();
2030 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002031 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002033 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002034
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002035 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002036 %LibInfo = ();
2037 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002038 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002040 %TemplateDecl = ();
2041 %StdCxxTypedef = ();
2042 %MissedTypedef = ();
2043 %Typedef_Tr = ();
2044 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002045 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002046
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002047 # clean cache
2048 delete($Cache{"getTypeAttr"});
2049 delete($Cache{"getTypeDeclId"});
2050
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002051 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002052 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002053 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002054 }
2055 else
2056 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002057 if($BinaryOnly and not $ExtendedCheck)
2058 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002059 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002060 }
2061 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002062 remove_Unused($Version, "Extended");
2063 }
2064 }
2065
2066 if($CheckInfo)
2067 {
2068 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2069 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2070 }
2071
2072 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2073 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002075 }
2076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002077 if($Debug) {
2078 # debugMangling($Version);
2079 }
2080}
2081
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002082sub readTUDump($)
2083{
2084 my $DumpPath = $_[0];
2085
2086 open(TU_DUMP, $DumpPath);
2087 local $/ = undef;
2088 my $Content = <TU_DUMP>;
2089 close(TU_DUMP);
2090
2091 unlink($DumpPath);
2092
2093 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002094 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002095
2096 # clean memory
2097 undef $Content;
2098
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002099 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002100
2101 foreach (0 .. $#Lines)
2102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002103 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002104 { # get a number and attributes of a node
2105 next if(not $NodeType{$2});
2106 $LibInfo{$Version}{"info_type"}{$1}=$2;
2107 $LibInfo{$Version}{"info"}{$1}=$3;
2108 }
2109
2110 # clean memory
2111 delete($Lines[$_]);
2112 }
2113
2114 # clean memory
2115 undef @Lines;
2116}
2117
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002118sub simplifyConstants()
2119{
2120 foreach my $Constant (keys(%{$Constants{$Version}}))
2121 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002122 if(defined $Constants{$Version}{$Constant}{"Header"})
2123 {
2124 my $Value = $Constants{$Version}{$Constant}{"Value"};
2125 if(defined $EnumConstants{$Version}{$Value}) {
2126 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2127 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002128 }
2129 }
2130}
2131
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002132sub simplifyNames()
2133{
2134 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2135 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002136 if($Typedef_Eq{$Version}{$Base}) {
2137 next;
2138 }
2139 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2140 if($#Translations==0)
2141 {
2142 if(length($Translations[0])<=length($Base)) {
2143 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2144 }
2145 }
2146 else
2147 { # select most appropriate
2148 foreach my $Tr (@Translations)
2149 {
2150 if($Base=~/\A\Q$Tr\E/)
2151 {
2152 $Typedef_Eq{$Version}{$Base} = $Tr;
2153 last;
2154 }
2155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002156 }
2157 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002158 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002159 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002160 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002161 if(not $TypeName) {
2162 next;
2163 }
2164 next if(index($TypeName,"<")==-1);# template instances only
2165 if($TypeName=~/>(::\w+)+\Z/)
2166 { # skip unused types
2167 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002168 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002169 foreach my $Base (sort {length($b)<=>length($a)}
2170 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002172 next if(not $Base);
2173 next if(index($TypeName,$Base)==-1);
2174 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002175 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002176 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002177 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2178 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2179 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002180 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002181 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2182 {
2183 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2184 {
2185 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2186 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002187 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002188 }
2189 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002192 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002193 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002194 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2195 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002196 }
2197}
2198
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002199sub setAnonTypedef_All()
2200{
2201 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2202 {
2203 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2204 {
2205 if(isAnon(getNameByInfo($InfoId))) {
2206 $TypedefToAnon{getTypeId($InfoId)} = 1;
2207 }
2208 }
2209 }
2210}
2211
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002212sub setTemplateParams_All()
2213{
2214 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2215 {
2216 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2217 setTemplateParams($_);
2218 }
2219 }
2220}
2221
2222sub setTemplateParams($)
2223{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002224 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002225 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002227 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002228 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002229 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002230 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002231 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002232 setTemplateInstParams($_[0], $TmplInst_Id);
2233 }
2234 }
2235
2236 $BasicTemplate{$Version}{$Tid} = $_[0];
2237
2238 if(my $Prms = getTreeAttr_Prms($_[0]))
2239 {
2240 if(my $Valu = getTreeAttr_Valu($Prms))
2241 {
2242 my $Vector = getTreeVec($Valu);
2243 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2244 {
2245 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2246 {
2247 if(my $Name = getNameByInfo($Val))
2248 {
2249 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2250 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2251 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2252 }
2253 else {
2254 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2255 }
2256 }
2257 }
2258 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002260 }
2261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002262 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002263 {
2264 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2265 {
2266 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002267 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002268 }
2269 }
2270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002271}
2272
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002273sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002274{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002275 my ($Tmpl, $Inst) = @_;
2276
2277 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002278 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002279 my ($Params_InfoId, $ElemId) = ();
2280 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2281 $Params_InfoId = $1;
2282 }
2283 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2284 $ElemId = $1;
2285 }
2286 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002287 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002288 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2289 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2290 {
2291 my ($PPos, $PTypeId) = ($1, $2);
2292 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2293 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002294 if($PType eq "template_type_parm") {
2295 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002296 }
2297 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002298 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2299 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002300 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002301 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002302 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002303 else
2304 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002305 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002306 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002308 }
2309 }
2310 }
2311}
2312
2313sub getTypeDeclId($)
2314{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002315 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002316 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002317 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2318 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2319 }
2320 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2321 {
2322 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2323 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2324 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002326 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002327 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002328}
2329
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002330sub getTypeInfo_All()
2331{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002332 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002333 { # support for GCC < 4.5
2334 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2335 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2336 # FIXME: check GCC versions
2337 addMissedTypes_Pre();
2338 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002339
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002340 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002341 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002342 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2343 if($IType=~/_type\Z/ and $IType ne "function_type"
2344 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002345 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002346 }
2347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002348
2349 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002350 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002351 "Name" => "...",
2352 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002353 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002354 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002355 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002356
2357 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002358 { # support for GCC < 4.5
2359 addMissedTypes_Post();
2360 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002361
2362 if($ADD_TMPL_INSTANCES)
2363 {
2364 # templates
2365 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2366 {
2367 if(defined $TemplateMap{$Version}{$Tid}
2368 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2369 {
2370 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2371 {
2372 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2373 {
2374 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2375 {
2376 if(my %MAttr = getTypeAttr($MembTypeId))
2377 {
2378 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2379 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2380 }
2381 }
2382 }
2383 }
2384 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2385 {
2386 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2387 {
2388 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2389
2390 if($NBid ne $Bid)
2391 {
2392 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2393 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2394 }
2395 }
2396 }
2397 }
2398 }
2399 }
2400}
2401
2402sub createType($$)
2403{
2404 my ($Attr, $LibVersion) = @_;
2405 my $NewId = ++$MAX_ID;
2406
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002407 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002408 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002409 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002410
2411 return "$NewId";
2412}
2413
2414sub instType($$$)
2415{ # create template instances
2416 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002417
2418 if(not $TypeInfo{$LibVersion}{$Tid}) {
2419 return undef;
2420 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002421 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2422
2423 foreach my $Key (sort keys(%{$Map}))
2424 {
2425 if(my $Val = $Map->{$Key})
2426 {
2427 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2428
2429 if(defined $Attr->{"NameSpace"}) {
2430 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2431 }
2432 foreach (keys(%{$Attr->{"TParam"}})) {
2433 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2434 }
2435 }
2436 else
2437 { # remove absent
2438 # _Traits, etc.
2439 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002440 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002441 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2442 }
2443 foreach (keys(%{$Attr->{"TParam"}}))
2444 {
2445 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2446 delete($Attr->{"TParam"}{$_});
2447 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002448 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002449 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2450 }
2451 }
2452 }
2453 }
2454
2455 my $Tmpl = 0;
2456
2457 if(defined $Attr->{"TParam"})
2458 {
2459 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2460 {
2461 my $PName = $Attr->{"TParam"}{$_}{"name"};
2462
2463 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2464 {
2465 my %Base = get_BaseType($PTid, $LibVersion);
2466
2467 if($Base{"Type"} eq "TemplateParam"
2468 or defined $Base{"Template"})
2469 {
2470 $Tmpl = 1;
2471 last
2472 }
2473 }
2474 }
2475 }
2476
2477 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2478 return "$Id";
2479 }
2480 else
2481 {
2482 if(not $Tmpl) {
2483 delete($Attr->{"Template"});
2484 }
2485
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002486 my $New = createType($Attr, $LibVersion);
2487
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002488 my %EMap = ();
2489 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2490 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2491 }
2492 foreach (keys(%{$Map})) {
2493 $EMap{$_} = $Map->{$_};
2494 }
2495
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002496 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2497 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002498 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002499 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002500 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002501 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002502 {
2503 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2504
2505 if($NBid ne $Bid)
2506 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002507 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2508 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002509 }
2510 }
2511 }
2512
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002513 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002514 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002515 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2516 {
2517 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2518 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2519 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002520 }
2521 }
2522
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002523 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002524 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002525 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2526 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002527 }
2528 }
2529
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002530 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2531 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002532 }
2533
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002534 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002536}
2537
2538sub addMissedTypes_Pre()
2539{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002540 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002541 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2542 { # detecting missed typedefs
2543 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2544 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002545 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002546 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002547 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002548 if($TypeType eq "Unknown")
2549 { # template_type_parm
2550 next;
2551 }
2552 my $TypeDeclId = getTypeDeclId($TypeId);
2553 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2554 my $TypedefName = getNameByInfo($MissedTDid);
2555 next if(not $TypedefName);
2556 next if($TypedefName eq "__float80");
2557 next if(isAnon($TypedefName));
2558 if(not $TypeDeclId
2559 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002560 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002561 }
2562 }
2563 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002564 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002565 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002566 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002567 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002568 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002569 next;
2570 }
2571 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002572 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002573 if(not $TypedefName) {
2574 next;
2575 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002576 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002577 my %MissedInfo = ( # typedef info
2578 "Name" => $TypedefName,
2579 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002580 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002582 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 my ($H, $L) = getLocation($MissedTDid);
2584 $MissedInfo{"Header"} = $H;
2585 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002586 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002587 { # other types
2588 next;
2589 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002590 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002591 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 next;
2593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002594 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002595 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002596 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002597 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002598 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002599 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 next;
2601 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002602 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 next;
2604 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002605 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 next;
2608 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002609 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 next;
2612 }
2613 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002614
2615 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002619 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002620 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002621 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002622
2623 # add missed & remove other
2624 $TypeInfo{$Version} = \%AddTypes;
2625 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626}
2627
2628sub addMissedTypes_Post()
2629{
2630 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2631 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002632 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2633 {
2634 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2635 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2636 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2637 }
2638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 }
2640}
2641
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002642sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002643{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002644 my $TypeId = $_[0];
2645 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2646 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002647 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002648 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650}
2651
2652sub getArraySize($$)
2653{
2654 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002655 if(my $Size = getSize($TypeId))
2656 {
2657 my $Elems = $Size/$BYTE_SIZE;
2658 while($BaseName=~s/\s*\[(\d+)\]//) {
2659 $Elems/=$1;
2660 }
2661 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2662 {
2663 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2664 $Elems/=$BasicSize;
2665 }
2666 }
2667 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002669 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002670}
2671
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002672sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002673{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002674 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002676 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2677 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002678 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002679 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2680 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2681 if(not $NodeType)
2682 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683 return ();
2684 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002685 if($NodeType eq "tree_vec")
2686 {
2687 if($Pos!=$#Positions)
2688 { # select last vector of parameters ( ns<P1>::type<P2> )
2689 next;
2690 }
2691 }
2692 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2693 foreach my $P (@Params)
2694 {
2695 if($P eq "") {
2696 return ();
2697 }
2698 elsif($P ne "\@skip\@") {
2699 @TmplParams = (@TmplParams, $P);
2700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002701 }
2702 }
2703 return @TmplParams;
2704}
2705
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002706sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002707{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002708 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002709 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002710 if(defined $TypeInfo{$Version}{$TypeId}
2711 and $TypeInfo{$Version}{$TypeId}{"Name"})
2712 { # already created
2713 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002714 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002715 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2716 { # incomplete type
2717 return ();
2718 }
2719 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2720
2721 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002723
2724 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2725 {
2726 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2727 {
2728 if($Info=~/qual[ ]*:/)
2729 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002730 my $NewId = ++$MAX_ID;
2731
2732 $MissedBase{$Version}{$TypeId} = "$NewId";
2733 $MissedBase_R{$Version}{$NewId} = $TypeId;
2734 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2735 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002736 }
2737 }
2738 $TypeAttr{"Type"} = "Typedef";
2739 }
2740 else {
2741 $TypeAttr{"Type"} = getTypeType($TypeId);
2742 }
2743
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002744 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2745 {
2746 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2747 { # local code
2748 return ();
2749 }
2750 }
2751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 if($TypeAttr{"Type"} eq "Unknown") {
2753 return ();
2754 }
2755 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2756 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002757 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002758 if(my $TName = $TypeAttr{"Name"})
2759 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002760 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002761 $TName_Tid{$Version}{$TName} = $TypeId;
2762 return %TypeAttr;
2763 }
2764 else {
2765 return ();
2766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 }
2768 elsif($TypeAttr{"Type"} eq "Array")
2769 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002770 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2771 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002772 return ();
2773 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002774 if(my $Algn = getAlgn($TypeId)) {
2775 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2776 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002777 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002778 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002780 if(not $BTAttr{"Name"}) {
2781 return ();
2782 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002783 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002785 if(my $Size = getSize($TypeId)) {
2786 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2787 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002788 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002789 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2790 }
2791 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002792 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002795 else
2796 {
2797 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002798 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002799 $TypeAttr{"Name"} = $1."[]".$2;
2800 }
2801 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002802 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002804 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002805 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002806 if($BTAttr{"Header"}) {
2807 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002809 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002810 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2811 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002812 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002813 return ();
2814 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002815 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002816 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002817 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002818 if($TypeAttr{"Name"})
2819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002821
2822 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2823 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002824 { # NOTE: register only one int: with built-in decl
2825 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2826 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2827 }
2828 }
2829 return %TypeAttr;
2830 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002831 else {
2832 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002834 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002835 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2836 {
2837 %TypeAttr = getTrivialTypeAttr($TypeId);
2838 if($TypeAttr{"Name"})
2839 {
2840 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2841 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2842 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2843 }
2844 return %TypeAttr;
2845 }
2846 else {
2847 return ();
2848 }
2849 }
2850 elsif($TypeAttr{"Type"} eq "SizeOf")
2851 {
2852 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2853 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2854 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2855 if($TypeAttr{"Name"})
2856 {
2857 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2858 return %TypeAttr;
2859 }
2860 else {
2861 return ();
2862 }
2863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002864 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002865 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002866 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2867 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002868 return ();
2869 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002870 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002871 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002872 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002873 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002874 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002875 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002876 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002878 }
2879 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002880 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002881 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 return ();
2884 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002885 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002886 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002887 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002889 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002890 }
2891 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002892 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 {
2894 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002895 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002896 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002897 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2899 }
2900 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002901 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
2903 }
2904 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002905 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 }
2907 if($TypeAttr{"Type"} eq "Typedef")
2908 {
2909 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002910
2911 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2912 return ();
2913 }
2914
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002915 if(isAnon($TypeAttr{"Name"}))
2916 { # anon typedef to anon type: ._N
2917 return ();
2918 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002919
2920 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2921 { # artificial typedef of "struct X" to "X"
2922 $TypeAttr{"Artificial"} = 1;
2923 }
2924
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002925 if(my $NS = getNameSpace($TypeDeclId))
2926 {
2927 my $TypeName = $TypeAttr{"Name"};
2928 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2929 { # "some_type" is the typedef to "struct some_type" in C++
2930 if($3) {
2931 $TypeAttr{"Name"} = $3."::".$TypeName;
2932 }
2933 }
2934 else
2935 {
2936 $TypeAttr{"NameSpace"} = $NS;
2937 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002938
2939 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2940 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2941 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002942 if($BTAttr{"NameSpace"}
2943 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002944 { # types like "std::fpos<__mbstate_t>" are
2945 # not covered by typedefs in the TU dump
2946 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002947 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2948 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002949 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002950 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002951 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002952 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002954 }
2955 }
2956 }
2957 }
2958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002959 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002961 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2963 { # typedef int*const TYPEDEF; // first
2964 # int foo(TYPEDEF p); // const is optimized out
2965 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2966 if($BTAttr{"Name"}=~/</)
2967 {
2968 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2969 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002971 }
2972 }
2973 }
2974 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2975 }
2976 if(not $TypeAttr{"Size"})
2977 {
2978 if($TypeAttr{"Type"} eq "Pointer") {
2979 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2980 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002981 elsif($BTAttr{"Size"}) {
2982 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002983 }
2984 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002985 if(my $Algn = getAlgn($TypeId)) {
2986 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2987 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002988 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002989 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2990 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002991 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002992 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002993 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002994 { # typedef to "class Class"
2995 # should not be registered in TName_Tid
2996 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2997 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002999 }
3000 return %TypeAttr;
3001 }
3002}
3003
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003004sub getTreeVec($)
3005{
3006 my %Vector = ();
3007 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3008 {
3009 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3010 { # string length is N-1 because of the null terminator
3011 $Vector{$1} = $2;
3012 }
3013 }
3014 return \%Vector;
3015}
3016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003017sub get_TemplateParam($$)
3018{
3019 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003020 return () if(not $Type_Id);
3021 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3022 return () if(not $NodeType);
3023 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003024 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003025 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003026 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003027 my $Num = getNodeIntCst($Type_Id);
3028 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003029 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 }
3031 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003032 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003033 }
3034 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003035 elsif($NodeType eq "string_cst") {
3036 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003037 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 elsif($NodeType eq "tree_vec")
3039 {
3040 my $Vector = getTreeVec($Type_Id);
3041 my @Params = ();
3042 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3043 {
3044 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3045 push(@Params, $P2);
3046 }
3047 }
3048 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003049 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003050 elsif($NodeType eq "parm_decl")
3051 {
3052 (getNameByInfo($Type_Id));
3053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003054 else
3055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003056 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003057 my $PName = $ParamAttr{"Name"};
3058 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003059 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003061 if($PName=~/\>/)
3062 {
3063 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 $PName = $Cover;
3065 }
3066 }
3067 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003068 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3070 # template<typename _Key, typename _Compare = std::less<_Key>
3071 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3072 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3073 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3074 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003075 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003077 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 }
3079}
3080
3081sub cover_stdcxx_typedef($)
3082{
3083 my $TypeName = $_[0];
3084 if(my @Covers = sort {length($a)<=>length($b)}
3085 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3086 { # take the shortest typedef
3087 # FIXME: there may be more than
3088 # one typedefs to the same type
3089 return $Covers[0];
3090 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003091 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3093 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3094 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003095 if(my $Cover = $Covers[0])
3096 {
3097 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3098 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003100 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003101 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102}
3103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003104sub getNodeIntCst($)
3105{
3106 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003108 if($EnumMembName_Id{$Version}{$CstId}) {
3109 return $EnumMembName_Id{$Version}{$CstId};
3110 }
3111 elsif((my $Value = getTreeValue($CstId)) ne "")
3112 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003113 if($Value eq "0")
3114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003115 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003116 return "false";
3117 }
3118 else {
3119 return "0";
3120 }
3121 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003122 elsif($Value eq "1")
3123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003124 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003125 return "true";
3126 }
3127 else {
3128 return "1";
3129 }
3130 }
3131 else {
3132 return $Value;
3133 }
3134 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003135 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136}
3137
3138sub getNodeStrCst($)
3139{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003140 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3141 {
3142 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003143 {
3144 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3145 { # string length is N-1 because of the null terminator
3146 return substr($1, 0, $2-1);
3147 }
3148 else
3149 { # identifier_node
3150 return substr($1, 0, $2);
3151 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003153 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003154 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003155}
3156
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003157sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003159 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003160 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3161 if($Type eq "FieldPtr") {
3162 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3163 }
3164 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3165 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003166 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167 if($Type eq "MethodPtr")
3168 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003169 if(my $Size = getSize($TypeId))
3170 {
3171 $Size/=$BYTE_SIZE;
3172 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003174 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003175 if(my $Algn = getAlgn($TypeId)) {
3176 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178 # Return
3179 if($Type eq "FieldPtr")
3180 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003181 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003182 if($ReturnAttr{"Name"}) {
3183 $MemPtrName .= $ReturnAttr{"Name"};
3184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185 $TypeAttr{"Return"} = $PtrId;
3186 }
3187 else
3188 {
3189 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3190 {
3191 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3193 if(not $ReturnAttr{"Name"})
3194 { # templates
3195 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003196 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198 $TypeAttr{"Return"} = $ReturnTypeId;
3199 }
3200 }
3201 # Class
3202 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3203 {
3204 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003205 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003206 if($Class{"Name"}) {
3207 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3208 }
3209 else {
3210 $MemPtrName .= " (*)";
3211 }
3212 }
3213 else {
3214 $MemPtrName .= " (*)";
3215 }
3216 # Parameters
3217 if($Type eq "FuncPtr"
3218 or $Type eq "MethodPtr")
3219 {
3220 my @ParamTypeName = ();
3221 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3222 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003223 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003224 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003225 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003227 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3228 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003230 my $PTypeId = $1;
3231 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003232 if(not $ParamAttr{"Name"})
3233 { # templates (template_type_parm), etc.
3234 return ();
3235 }
3236 if($ParamAttr{"Name"} eq "void") {
3237 last;
3238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003239 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003240 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003241 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003242 push(@ParamTypeName, $ParamAttr{"Name"});
3243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003244 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3245 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003246 }
3247 else {
3248 last;
3249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003250 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 else {
3252 last;
3253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003254 }
3255 }
3256 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3257 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003258 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259 return %TypeAttr;
3260}
3261
3262sub getTreeTypeName($)
3263{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003264 my $TypeId = $_[0];
3265 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003266 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003267 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003268 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003269 if(my $Name = getNameByInfo($TypeId))
3270 { # bit_size_type
3271 return $Name;
3272 }
3273 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 return "unsigned int";
3275 }
3276 else {
3277 return "int";
3278 }
3279 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003280 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003281 return getNameByInfo($1);
3282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003284 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285}
3286
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003287sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003289 my $Ptd = pointTo($_[0]);
3290 return 0 if(not $Ptd);
3291 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003292 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003293 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3294 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003295 }
3296 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003297 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3298 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003299 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300 if($InfoT1 eq "pointer_type"
3301 and $InfoT2 eq "function_type") {
3302 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303 }
3304 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003305 return 0;
3306}
3307
3308sub isMethodPtr($)
3309{
3310 my $Ptd = pointTo($_[0]);
3311 return 0 if(not $Ptd);
3312 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3313 {
3314 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3315 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3316 and $Info=~/ ptrmem /) {
3317 return 1;
3318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320 return 0;
3321}
3322
3323sub isFieldPtr($)
3324{
3325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3326 {
3327 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3328 and $Info=~/ ptrmem /) {
3329 return 1;
3330 }
3331 }
3332 return 0;
3333}
3334
3335sub pointTo($)
3336{
3337 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3338 {
3339 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3340 return $1;
3341 }
3342 }
3343 return "";
3344}
3345
3346sub getTypeTypeByTypeId($)
3347{
3348 my $TypeId = $_[0];
3349 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3350 {
3351 my $NType = $NodeType{$TType};
3352 if($NType eq "Intrinsic") {
3353 return $NType;
3354 }
3355 elsif(isFuncPtr($TypeId)) {
3356 return "FuncPtr";
3357 }
3358 elsif(isMethodPtr($TypeId)) {
3359 return "MethodPtr";
3360 }
3361 elsif(isFieldPtr($TypeId)) {
3362 return "FieldPtr";
3363 }
3364 elsif($NType ne "Other") {
3365 return $NType;
3366 }
3367 }
3368 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003369}
3370
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003371my %UnQual = (
3372 "r"=>"restrict",
3373 "v"=>"volatile",
3374 "c"=>"const",
3375 "cv"=>"const volatile"
3376);
3377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378sub getQual($)
3379{
3380 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003381 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3382 {
3383 my ($Qual, $To) = ();
3384 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3385 $Qual = $UnQual{$1};
3386 }
3387 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3388 $To = $1;
3389 }
3390 if($Qual and $To) {
3391 return ($Qual, $To);
3392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393 }
3394 return ();
3395}
3396
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003397sub getQualType($)
3398{
3399 if($_[0] eq "const volatile") {
3400 return "ConstVolatile";
3401 }
3402 return ucfirst($_[0]);
3403}
3404
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003405sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003406{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003407 my $TypeId = $_[0];
3408 my $TypeDeclId = getTypeDeclId($TypeId);
3409 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003410 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003411 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3412 return "Typedef";
3413 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003414 }
3415 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3416 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003417 if(($Qual or $To) and $TypeDeclId
3418 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003419 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003421 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003422 elsif(not $MissedBase_R{$Version}{$TypeId}
3423 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003424 return "Typedef";
3425 }
3426 elsif($Qual)
3427 { # qualified types
3428 return getQualType($Qual);
3429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003430
3431 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3432 { # typedef struct { ... } name
3433 $TypeTypedef{$Version}{$TypeId} = $1;
3434 }
3435
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 my $TypeType = getTypeTypeByTypeId($TypeId);
3437 if($TypeType eq "Struct")
3438 {
3439 if($TypeDeclId
3440 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3441 return "Template";
3442 }
3443 }
3444 return $TypeType;
3445}
3446
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003447sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003448{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003449 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003450 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003451 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3452 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3453 return 0;
3454 }
3455 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3456 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003457 if(my $TDid = getTypeDeclId($_[0]))
3458 {
3459 if(getTypeId($TDid) eq $_[0]
3460 and getNameByInfo($TDid))
3461 {
3462 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3463 return $1;
3464 }
3465 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003467 }
3468 }
3469 return 0;
3470}
3471
3472sub selectBaseType($)
3473{
3474 my $TypeId = $_[0];
3475 if(defined $MissedTypedef{$Version}{$TypeId})
3476 { # add missed typedefs
3477 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3478 return ($TypeId, "");
3479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003480 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003481 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3482 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003483
3484 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3485 my $MB = $MissedBase{$Version}{$TypeId};
3486
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003487 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003488 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489 and (getTypeId($1) ne $TypeId)
3490 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003491 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003492 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003493 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003494 elsif($MB)
3495 { # add base
3496 return ($MB, "");
3497 }
3498 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003499 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003500 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003501 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003502 elsif($Qual or $To)
3503 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003504 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003505 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003506 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003507 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003508 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003511 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003512 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003513 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003514 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003517 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003518 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003519 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003520 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003521 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003523 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003524
3525 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526}
3527
3528sub getSymbolInfo_All()
3529{
3530 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3531 { # reverse order
3532 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003533 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 }
3535 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003536
3537 if($ADD_TMPL_INSTANCES)
3538 {
3539 # templates
3540 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3541 {
3542 my %Map = ();
3543
3544 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3545 {
3546 if(defined $TemplateMap{$Version}{$ClassId})
3547 {
3548 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3549 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3550 }
3551 }
3552 }
3553
3554 if(defined $TemplateMap{$Version}{$Sid})
3555 {
3556 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3557 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3558 }
3559 }
3560
3561 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3562 {
3563 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3564 {
3565 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3566 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3567 }
3568 }
3569 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3570 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3571 }
3572 }
3573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003574}
3575
3576sub getVarInfo_All()
3577{
3578 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3579 { # reverse order
3580 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003581 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003582 }
3583 }
3584}
3585
3586sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003587 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588}
3589
3590sub getVarInfo($)
3591{
3592 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003593 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003594 {
3595 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3596 if($NSInfoType and $NSInfoType eq "function_decl") {
3597 return;
3598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003599 }
3600 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3601 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3602 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3603 delete($SymbolInfo{$Version}{$InfoId});
3604 return;
3605 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003606 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003607 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003608 delete($SymbolInfo{$Version}{$InfoId});
3609 return;
3610 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003611 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3612 delete($SymbolInfo{$Version}{$InfoId});
3613 return;
3614 }
3615 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003616 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3617 {
3618 if($OSgroup eq "windows")
3619 { # cut the offset
3620 $MnglName=~s/\@\d+\Z//g;
3621 }
3622 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003624 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003625 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003626 { # validate mangled name
3627 delete($SymbolInfo{$Version}{$InfoId});
3628 return;
3629 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003630 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003631 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003632 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003633 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003634 }
3635 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3636 { # non-public global data
3637 delete($SymbolInfo{$Version}{$InfoId});
3638 return;
3639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003640 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003641 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003642 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003643 if(not defined $TypeInfo{$Version}{$Rid}
3644 or not $TypeInfo{$Version}{$Rid}{"Name"})
3645 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003646 delete($SymbolInfo{$Version}{$InfoId});
3647 return;
3648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003649 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3650 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003651 if(defined $Val) {
3652 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003654 }
3655 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003656 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3657 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003658 if(not defined $TypeInfo{$Version}{$ClassId}
3659 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3660 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 delete($SymbolInfo{$Version}{$InfoId});
3662 return;
3663 }
3664 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003665 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3666 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003668 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003670 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003671 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003672 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003674 if(not $CheckHeadersOnly)
3675 {
3676 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3677 {
3678 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3679 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3680 {
3681 if(link_symbol($ShortName, $Version, "-Deps"))
3682 { # "const" global data is mangled as _ZL... in the TU dump
3683 # but not mangled when compiling a C shared library
3684 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3685 }
3686 }
3687 }
3688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 if($COMMON_LANGUAGE{$Version} eq "C++")
3690 {
3691 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3692 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003693 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3695 }
3696 }
3697 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3698 { # try to mangle symbol (link with libraries)
3699 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3700 }
3701 if($OStarget eq "windows")
3702 {
3703 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3704 { # link MS C++ symbols from library with GCC symbols from headers
3705 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3706 }
3707 }
3708 }
3709 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3710 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3711 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003712 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3713 {
3714 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3715 { # non-target symbols
3716 delete($SymbolInfo{$Version}{$InfoId});
3717 return;
3718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003720 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3721 {
3722 if(defined $MissedTypedef{$Version}{$Rid})
3723 {
3724 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3725 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3726 }
3727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003728 }
3729 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003730 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3732 }
3733 if($ShortName=~/\A(_Z|\?)/) {
3734 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3735 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003736
3737 if($ExtraDump) {
3738 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740}
3741
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003742sub isConstType($$)
3743{
3744 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003745 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003746 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003747 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003748 }
3749 return ($Base{"Type"} eq "Const");
3750}
3751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003752sub getTrivialName($$)
3753{
3754 my ($TypeInfoId, $TypeId) = @_;
3755 my %TypeAttr = ();
3756 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3757 if(not $TypeAttr{"Name"}) {
3758 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3759 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003760 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003761 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003762 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003763 if(isAnon($TypeAttr{"Name"}))
3764 {
3765 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003766 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003767 { # searching for a first not anon scope
3768 if($NSId eq $NameSpaceId) {
3769 last;
3770 }
3771 else
3772 {
3773 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3774 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003775 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003776 last;
3777 }
3778 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003779 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003780 }
3781 }
3782 else
3783 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003784 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003785 {
3786 if($NameSpaceId ne $TypeId) {
3787 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789 }
3790 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003791 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003792 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3793 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003794 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003795 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003796 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003797 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003798 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003799 if($TypeAttr{"NameSpace"}) {
3800 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003802 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003803 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3804 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003805 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003806 if(my @TParams = getTParams($TypeId, "Type")) {
3807 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3808 }
3809 else {
3810 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 }
3813 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3814}
3815
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003816sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003818 my $TypeId = $_[0];
3819 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003820
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003821 my %TypeAttr = ();
3822
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003823 if($TemplateDecl{$Version}{$TypeId})
3824 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003825 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003826 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828 setTypeAccess($TypeId, \%TypeAttr);
3829 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3830 if(isBuiltIn($TypeAttr{"Header"}))
3831 {
3832 delete($TypeAttr{"Header"});
3833 delete($TypeAttr{"Line"});
3834 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003835
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003836 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3838 if(not $TypeAttr{"Name"}) {
3839 return ();
3840 }
3841 if(not $TypeAttr{"NameSpace"}) {
3842 delete($TypeAttr{"NameSpace"});
3843 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003844
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003845 if($TypeAttr{"Type"} eq "Intrinsic")
3846 {
3847 if(defined $TypeAttr{"Header"})
3848 {
3849 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3850 { # support for SUSE 11.2
3851 # integer_type has srcp dump{1-2}.i
3852 delete($TypeAttr{"Header"});
3853 }
3854 }
3855 }
3856
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003857 my $Tmpl = undef;
3858
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003859 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003860 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003861 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3862
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003863 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003864 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003865 foreach my $Pos (0 .. $#TParams)
3866 {
3867 my $Val = $TParams[$Pos];
3868 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3869
3870 if(not defined $TypeAttr{"Template"})
3871 {
3872 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3873
3874 if($Base{"Type"} eq "TemplateParam"
3875 or defined $Base{"Template"}) {
3876 $TypeAttr{"Template"} = 1;
3877 }
3878 }
3879
3880 if($Tmpl)
3881 {
3882 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3883 {
3884 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3885
3886 if($Val eq $Arg) {
3887 $TypeAttr{"Template"} = 1;
3888 }
3889 }
3890 }
3891 }
3892
3893 if($Tmpl)
3894 {
3895 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3896 {
3897 if($Pos>$#TParams)
3898 {
3899 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3900 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3901 }
3902 }
3903 }
3904 }
3905
3906 if($ADD_TMPL_INSTANCES)
3907 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003908 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003909 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003910 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003911 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003912 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003913 {
3914 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3915 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3916 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003917 }
3918 if(not getTreeAttr_Binf($TypeId))
3919 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003920 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3921 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3922 }
3923 }
3924 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003925 }
3926 }
3927 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003928
3929 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3930
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003931 if(my $Size = getSize($TypeId))
3932 {
3933 $Size = $Size/$BYTE_SIZE;
3934 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003936 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003937 {
3938 if($ExtraDump)
3939 {
3940 if(not defined $TypeAttr{"Memb"}
3941 and not $Tmpl)
3942 { # declaration only
3943 $TypeAttr{"Forward"} = 1;
3944 }
3945 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003946 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003947
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003948 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003949 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003950 {
3951 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003952 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003953 }
3954 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003955 or $TypeAttr{"Type"} eq "Class")
3956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003957 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003958 if($Skip) {
3959 return ();
3960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003961 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003962 if(my $Algn = getAlgn($TypeId)) {
3963 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003965 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003966
3967 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3968 {
3969 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003970 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003971 {
3972 if(not isAnon($TypeAttr{"Name"})) {
3973 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3974 }
3975 }
3976 }
3977
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003978 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003979 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3980 {
3981 my @Entries = split(/\n/, $VTable);
3982 foreach (1 .. $#Entries)
3983 {
3984 my $Entry = $Entries[$_];
3985 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003986 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003987 }
3988 }
3989 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003990
3991 if($TypeAttr{"Type"} eq "Enum")
3992 {
3993 if(not $TypeAttr{"NameSpace"})
3994 {
3995 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
3996 {
3997 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003998 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003999 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004000 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004001 "Header"=>$TypeAttr{"Header"}
4002 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004003 if(isAnon($TypeAttr{"Name"}))
4004 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004005 if($ExtraDump
4006 or is_target_header($TypeAttr{"Header"}, $Version))
4007 {
4008 %{$Constants{$Version}{$MName}} = (
4009 "Value" => $MVal,
4010 "Header" => $TypeAttr{"Header"}
4011 );
4012 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004013 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004014 }
4015 }
4016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004017 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004018 {
4019 if(defined $TypedefToAnon{$TypeId}) {
4020 $TypeAttr{"AnonTypedef"} = 1;
4021 }
4022 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004024 return %TypeAttr;
4025}
4026
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004027sub simplifyVTable($)
4028{
4029 my $Content = $_[0];
4030 if($Content=~s/ \[with (.+)]//)
4031 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4032 if(my @Elems = separate_Params($1, 0, 0))
4033 {
4034 foreach my $Elem (@Elems)
4035 {
4036 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4037 {
4038 my ($Arg, $Val) = ($1, $2);
4039
4040 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4041 $Content=~s/,\s*$Arg\b//g;
4042 }
4043 else {
4044 $Content=~s/\b$Arg\b/$Val/g;
4045 }
4046 }
4047 }
4048 }
4049 }
4050
4051 return $Content;
4052}
4053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004054sub detect_lang($)
4055{
4056 my $TypeId = $_[0];
4057 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004058 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004059 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004060 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4061 }
4062 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004063 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004064 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004065 while($Fncs)
4066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004067 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004068 return 1;
4069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004070 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004071 }
4072 }
4073 return 0;
4074}
4075
4076sub setSpec($$)
4077{
4078 my ($TypeId, $TypeAttr) = @_;
4079 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4080 if($Info=~/\s+spec\s+/) {
4081 $TypeAttr->{"Spec"} = 1;
4082 }
4083}
4084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004085sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004086{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004087 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004088 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004089 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004090 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004091 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004092 my $Pos = 0;
4093 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4094 {
4095 my ($Access, $BInfoId) = ($1, $2);
4096 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004097
4098 if($ClassId==$TypeId)
4099 { # class A<N>:public A<N-1>
4100 next;
4101 }
4102
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004103 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4104 if(not $CType or $CType eq "template_type_parm"
4105 or $CType eq "typename_type")
4106 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004107 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004109 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004110 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4112 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004113 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004114 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4115 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004116 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004117 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004118 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4120 }
4121 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004122 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123 }
4124 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004125 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004126}
4127
4128sub getBinfClassId($)
4129{
4130 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4131 $Info=~/type[ ]*:[ ]*@(\d+) /;
4132 return $1;
4133}
4134
4135sub unmangledFormat($$)
4136{
4137 my ($Name, $LibVersion) = @_;
4138 $Name = uncover_typedefs($Name, $LibVersion);
4139 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4140 $Name=~s/\(\w+\)(\d)/$1/;
4141 return $Name;
4142}
4143
4144sub modelUnmangled($$)
4145{
4146 my ($InfoId, $Compiler) = @_;
4147 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4148 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4149 }
4150 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4151 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4152 $PureSignature = "~".$PureSignature;
4153 }
4154 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4155 {
4156 my (@Params, @ParamTypes) = ();
4157 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4158 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4159 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4160 }
4161 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4162 { # checking parameters
4163 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004164 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004165 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004166 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004167
4168 if($PName eq "this"
4169 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4170 {
4171 next;
4172 }
4173
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004174 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004175 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004176 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004177 }
4178 @ParamTypes = (@ParamTypes, $PTName);
4179 }
4180 if(@ParamTypes) {
4181 $PureSignature .= "(".join(", ", @ParamTypes).")";
4182 }
4183 else
4184 {
4185 if($Compiler eq "MSVC")
4186 {
4187 $PureSignature .= "(void)";
4188 }
4189 else
4190 { # GCC
4191 $PureSignature .= "()";
4192 }
4193 }
4194 $PureSignature = delete_keywords($PureSignature);
4195 }
4196 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4197 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004198 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004199 $PureSignature = $ClassName."::".$PureSignature;
4200 }
4201 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4202 $PureSignature = $NS."::".$PureSignature;
4203 }
4204 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4205 $PureSignature .= " const";
4206 }
4207 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4208 $PureSignature .= " volatile";
4209 }
4210 my $ShowReturn = 0;
4211 if($Compiler eq "MSVC"
4212 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4213 {
4214 $ShowReturn=1;
4215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004216 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4217 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004218 {
4219 $ShowReturn=1;
4220 }
4221 if($ShowReturn)
4222 { # mangled names for template function specializations include return value
4223 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4224 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004225 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4227 $PureSignature = $ReturnName." ".$PureSignature;
4228 }
4229 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004230 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004231}
4232
4233sub mangle_symbol($$$)
4234{ # mangling for simple methods
4235 # see gcc-4.6.0/gcc/cp/mangle.c
4236 my ($InfoId, $LibVersion, $Compiler) = @_;
4237 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4238 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4239 }
4240 my $Mangled = "";
4241 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004242 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 }
4244 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004245 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004246 }
4247 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4248}
4249
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004250sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004251{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004252 my ($InfoId, $LibVersion) = @_;
4253 return "";
4254}
4255
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004256sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257{ # see gcc-4.6.0/gcc/cp/mangle.c
4258 my ($InfoId, $LibVersion) = @_;
4259 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004260 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 my %Repl = ();# SN_ replacements
4262 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4263 {
4264 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4265 if($MangledClass!~/\AN/) {
4266 $MangledClass = "N".$MangledClass;
4267 }
4268 else {
4269 $MangledClass=~s/E\Z//;
4270 }
4271 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4272 $MangledClass=~s/\AN/NV/;
4273 }
4274 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4275 $MangledClass=~s/\AN/NK/;
4276 }
4277 $Mangled .= $MangledClass;
4278 }
4279 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4280 { # mangled by name due to the absence of structured info
4281 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4282 if($MangledNS!~/\AN/) {
4283 $MangledNS = "N".$MangledNS;
4284 }
4285 else {
4286 $MangledNS=~s/E\Z//;
4287 }
4288 $Mangled .= $MangledNS;
4289 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004290 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004291 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004292 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004293 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004294 foreach (@TPos) {
4295 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4296 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004297 }
4298 elsif($TmplParams)
4299 { # remangling mode
4300 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004301 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004302 }
4303 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4304 $Mangled .= "C1";
4305 }
4306 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4307 $Mangled .= "D0";
4308 }
4309 elsif($ShortName)
4310 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004311 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4312 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004313 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004314 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004315 { # "const" global data is mangled as _ZL...
4316 $Mangled .= "L";
4317 }
4318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004319 if($ShortName=~/\Aoperator(\W.*)\Z/)
4320 {
4321 my $Op = $1;
4322 $Op=~s/\A[ ]+//g;
4323 if(my $OpMngl = $OperatorMangling{$Op}) {
4324 $Mangled .= $OpMngl;
4325 }
4326 else { # conversion operator
4327 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4328 }
4329 }
4330 else {
4331 $Mangled .= length($ShortName).$ShortName;
4332 }
4333 if(@TParams)
4334 { # templates
4335 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004336 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004337 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4338 }
4339 $Mangled .= "E";
4340 }
4341 if(not $ClassId and @TParams) {
4342 add_substitution($ShortName, \%Repl, 0);
4343 }
4344 }
4345 if($ClassId or $NameSpace) {
4346 $Mangled .= "E";
4347 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004348 if(@TParams)
4349 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004350 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004351 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4352 }
4353 }
4354 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4355 {
4356 my @Params = ();
4357 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4358 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4359 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4360 }
4361 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4362 { # checking parameters
4363 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4364 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4365 }
4366 if(not @Params) {
4367 $Mangled .= "v";
4368 }
4369 }
4370 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4371 $Mangled = write_stdcxx_substitution($Mangled);
4372 if($Mangled eq "_Z") {
4373 return "";
4374 }
4375 return $Mangled;
4376}
4377
4378sub correct_incharge($$$)
4379{
4380 my ($InfoId, $LibVersion, $Mangled) = @_;
4381 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4382 {
4383 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004384 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004385 }
4386 }
4387 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4388 {
4389 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004390 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004391 }
4392 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004393 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004394 }
4395 }
4396 return $Mangled;
4397}
4398
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004399sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004400{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004401 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004402 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004403 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004404 return $Name;
4405 }
4406 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004407 while(my $CPos = find_center($TParams, "<"))
4408 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 $TParams = substr($TParams, $CPos);
4410 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004411 if($TParams=~s/\A<(.+)>\Z/$1/) {
4412 $Name=~s/<\Q$TParams\E>\Z//;
4413 }
4414 else
4415 { # error
4416 $TParams = "";
4417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004418 return ($Name, $TParams);
4419}
4420
4421sub get_sub_ns($)
4422{
4423 my $Name = $_[0];
4424 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004425 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004426 {
4427 push(@NS, substr($Name, 0, $CPos));
4428 $Name = substr($Name, $CPos);
4429 $Name=~s/\A:://;
4430 }
4431 return (join("::", @NS), $Name);
4432}
4433
4434sub mangle_ns($$$)
4435{
4436 my ($Name, $LibVersion, $Repl) = @_;
4437 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4438 {
4439 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4440 $Mangled=~s/\AN(.+)E\Z/$1/;
4441 return $Mangled;
4442
4443 }
4444 else
4445 {
4446 my ($MangledNS, $SubNS) = ("", "");
4447 ($SubNS, $Name) = get_sub_ns($Name);
4448 if($SubNS) {
4449 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4450 }
4451 $MangledNS .= length($Name).$Name;
4452 add_substitution($MangledNS, $Repl, 0);
4453 return $MangledNS;
4454 }
4455}
4456
4457sub mangle_param($$$)
4458{
4459 my ($PTid, $LibVersion, $Repl) = @_;
4460 my ($MPrefix, $Mangled) = ("", "");
4461 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004462 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004463 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004464 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004465 if(not $BaseType_Name) {
4466 return "";
4467 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004468 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004469 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004470 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4471 while($Suffix=~/(&|\*|const)\Z/)
4472 {
4473 if($Suffix=~s/[ ]*&\Z//) {
4474 $MPrefix .= "R";
4475 }
4476 if($Suffix=~s/[ ]*\*\Z//) {
4477 $MPrefix .= "P";
4478 }
4479 if($Suffix=~s/[ ]*const\Z//)
4480 {
4481 if($MPrefix=~/R|P/
4482 or $Suffix=~/&|\*/) {
4483 $MPrefix .= "K";
4484 }
4485 }
4486 if($Suffix=~s/[ ]*volatile\Z//) {
4487 $MPrefix .= "V";
4488 }
4489 #if($Suffix=~s/[ ]*restrict\Z//) {
4490 #$MPrefix .= "r";
4491 #}
4492 }
4493 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4494 $Mangled .= $Token;
4495 }
4496 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4497 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004498 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004499 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004500 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004501 foreach (@TPos) {
4502 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4503 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004504 }
4505 elsif($TmplParams)
4506 { # remangling mode
4507 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004508 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004509 }
4510 my $MangledNS = "";
4511 my ($SubNS, $SName) = get_sub_ns($ShortName);
4512 if($SubNS) {
4513 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4514 }
4515 $MangledNS .= length($SName).$SName;
4516 if(@TParams) {
4517 add_substitution($MangledNS, $Repl, 0);
4518 }
4519 $Mangled .= "N".$MangledNS;
4520 if(@TParams)
4521 { # templates
4522 $Mangled .= "I";
4523 foreach my $TParam (@TParams) {
4524 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4525 }
4526 $Mangled .= "E";
4527 }
4528 $Mangled .= "E";
4529 }
4530 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4531 {
4532 if($BaseType{"Type"} eq "MethodPtr") {
4533 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4534 }
4535 else {
4536 $Mangled .= "PF";
4537 }
4538 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4539 my @Params = keys(%{$BaseType{"Param"}});
4540 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4541 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4542 }
4543 if(not @Params) {
4544 $Mangled .= "v";
4545 }
4546 $Mangled .= "E";
4547 }
4548 elsif($BaseType{"Type"} eq "FieldPtr")
4549 {
4550 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4551 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4552 }
4553 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4554 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4555 {
4556 if($Mangled eq $Optimized)
4557 {
4558 if($ShortName!~/::/)
4559 { # remove "N ... E"
4560 if($MPrefix) {
4561 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4562 }
4563 else {
4564 $Mangled=~s/\AN(.+)E\Z/$1/g;
4565 }
4566 }
4567 }
4568 else {
4569 $Mangled = $Optimized;
4570 }
4571 }
4572 add_substitution($Mangled, $Repl, 1);
4573 return $Mangled;
4574}
4575
4576sub mangle_template_param($$$)
4577{ # types + literals
4578 my ($TParam, $LibVersion, $Repl) = @_;
4579 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4580 return mangle_param($TPTid, $LibVersion, $Repl);
4581 }
4582 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4583 { # class_name<1u>::method(...)
4584 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4585 }
4586 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4587 { # class_name<(signed char)1>::method(...)
4588 return "L".$IntrinsicMangling{$1}.$2."E";
4589 }
4590 elsif($TParam eq "true")
4591 { # class_name<true>::method(...)
4592 return "Lb1E";
4593 }
4594 elsif($TParam eq "false")
4595 { # class_name<true>::method(...)
4596 return "Lb0E";
4597 }
4598 else { # internal error
4599 return length($TParam).$TParam;
4600 }
4601}
4602
4603sub add_substitution($$$)
4604{
4605 my ($Value, $Repl, $Rec) = @_;
4606 if($Rec)
4607 { # subtypes
4608 my @Subs = ($Value);
4609 while($Value=~s/\A(R|P|K)//) {
4610 push(@Subs, $Value);
4611 }
4612 foreach (reverse(@Subs)) {
4613 add_substitution($_, $Repl, 0);
4614 }
4615 return;
4616 }
4617 return if($Value=~/\AS(\d*)_\Z/);
4618 $Value=~s/\AN(.+)E\Z/$1/g;
4619 return if(defined $Repl->{$Value});
4620 return if(length($Value)<=1);
4621 return if($StdcxxMangling{$Value});
4622 # check for duplicates
4623 my $Base = $Value;
4624 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4625 {
4626 my $Num = $Repl->{$Type};
4627 my $Replace = macro_mangle($Num);
4628 $Base=~s/\Q$Replace\E/$Type/;
4629 }
4630 if(my $OldNum = $Repl->{$Base})
4631 {
4632 $Repl->{$Value} = $OldNum;
4633 return;
4634 }
4635 my @Repls = sort {$b<=>$a} values(%{$Repl});
4636 if(@Repls) {
4637 $Repl->{$Value} = $Repls[0]+1;
4638 }
4639 else {
4640 $Repl->{$Value} = -1;
4641 }
4642 # register duplicates
4643 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004644 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004645 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4646 {
4647 next if($Base eq $Type);
4648 my $Num = $Repl->{$Type};
4649 my $Replace = macro_mangle($Num);
4650 $Base=~s/\Q$Type\E/$Replace/;
4651 $Repl->{$Base} = $Repl->{$Value};
4652 }
4653}
4654
4655sub macro_mangle($)
4656{
4657 my $Num = $_[0];
4658 if($Num==-1) {
4659 return "S_";
4660 }
4661 else
4662 {
4663 my $Code = "";
4664 if($Num<10)
4665 { # S0_, S1_, S2_, ...
4666 $Code = $Num;
4667 }
4668 elsif($Num>=10 and $Num<=35)
4669 { # SA_, SB_, SC_, ...
4670 $Code = chr(55+$Num);
4671 }
4672 else
4673 { # S10_, S11_, S12_
4674 $Code = $Num-26; # 26 is length of english alphabet
4675 }
4676 return "S".$Code."_";
4677 }
4678}
4679
4680sub write_stdcxx_substitution($)
4681{
4682 my $Mangled = $_[0];
4683 if($StdcxxMangling{$Mangled}) {
4684 return $StdcxxMangling{$Mangled};
4685 }
4686 else
4687 {
4688 my @Repls = keys(%StdcxxMangling);
4689 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4690 foreach my $MangledType (@Repls)
4691 {
4692 my $Replace = $StdcxxMangling{$MangledType};
4693 #if($Mangled!~/$Replace/) {
4694 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4695 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4696 #}
4697 }
4698 }
4699 return $Mangled;
4700}
4701
4702sub write_substitution($$)
4703{
4704 my ($Mangled, $Repl) = @_;
4705 if(defined $Repl->{$Mangled}
4706 and my $MnglNum = $Repl->{$Mangled}) {
4707 $Mangled = macro_mangle($MnglNum);
4708 }
4709 else
4710 {
4711 my @Repls = keys(%{$Repl});
4712 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4713 # FIXME: how to apply replacements? by num or by pos
4714 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4715 foreach my $MangledType (@Repls)
4716 {
4717 my $Replace = macro_mangle($Repl->{$MangledType});
4718 if($Mangled!~/$Replace/) {
4719 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4720 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4721 }
4722 }
4723 }
4724 return $Mangled;
4725}
4726
4727sub delete_keywords($)
4728{
4729 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004730 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004731 return $TypeName;
4732}
4733
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004734sub uncover_typedefs($$)
4735{
4736 my ($TypeName, $LibVersion) = @_;
4737 return "" if(not $TypeName);
4738 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4739 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4740 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004741 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004742 while($TypeName_New ne $TypeName_Pre)
4743 {
4744 $TypeName_Pre = $TypeName_New;
4745 my $TypeName_Copy = $TypeName_New;
4746 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004747 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004748 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004749 if(not $Intrinsic_Keywords{$1}) {
4750 $Words{$1} = 1;
4751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004752 }
4753 foreach my $Word (keys(%Words))
4754 {
4755 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4756 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004757 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004758 if($BaseType_Name=~/\([\*]+\)/)
4759 { # FuncPtr
4760 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4761 {
4762 my $Type_Suffix = $1;
4763 $TypeName_New = $BaseType_Name;
4764 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004765 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004766 }
4767 }
4768 }
4769 else
4770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004771 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004772 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004773 }
4774 }
4775 }
4776 }
4777 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4778}
4779
4780sub isInternal($)
4781{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4783 {
4784 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4785 {
4786 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4787 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4788 return 1;
4789 }
4790 }
4791 }
4792 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004793}
4794
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004795sub getDataVal($$)
4796{
4797 my ($InfoId, $TypeId) = @_;
4798 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4799 {
4800 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4801 {
4802 if(defined $LibInfo{$Version}{"info_type"}{$1}
4803 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004804 {
4805 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004806 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004807 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4808 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004809 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004810 if(my $Addr = getTreeAttr_Op($1)) {
4811 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004812 }
4813 }
4814 }
4815 }
4816 else {
4817 return getInitVal($1, $TypeId);
4818 }
4819 }
4820 }
4821 return undef;
4822}
4823
4824sub getInitVal($$)
4825{
4826 my ($InfoId, $TypeId) = @_;
4827 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4828 {
4829 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4830 {
4831 if($InfoType eq "integer_cst")
4832 {
4833 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004834 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004835 { # characters
4836 $Val = chr($Val);
4837 }
4838 return $Val;
4839 }
4840 elsif($InfoType eq "string_cst") {
4841 return getNodeStrCst($InfoId);
4842 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004843 elsif($InfoType eq "var_decl")
4844 {
4845 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4846 return $Name;
4847 }
4848 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004849 }
4850 }
4851 return undef;
4852}
4853
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004854sub set_Class_And_Namespace($)
4855{
4856 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004857 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004858 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004859 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004860 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004861 my $NSInfoId = $1;
4862 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4863 {
4864 if($InfoType eq "namespace_decl") {
4865 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4866 }
4867 elsif($InfoType eq "record_type") {
4868 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4869 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004871 }
4872 }
4873 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4874 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004875 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004876 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004877 { # skip
4878 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004880 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004881
4882 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004883}
4884
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004885sub debugMangling($)
4886{
4887 my $LibVersion = $_[0];
4888 my %Mangled = ();
4889 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4890 {
4891 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4892 {
4893 if($Mngl=~/\A(_Z|\?)/) {
4894 $Mangled{$Mngl}=$InfoId;
4895 }
4896 }
4897 }
4898 translateSymbols(keys(%Mangled), $LibVersion);
4899 foreach my $Mngl (keys(%Mangled))
4900 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004901 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4902 my $U2 = $tr_name{$Mngl};
4903 if($U1 ne $U2) {
4904 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004905 }
4906 }
4907}
4908
4909sub linkSymbol($)
4910{ # link symbols from shared libraries
4911 # with the symbols from header files
4912 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004913 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004914 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004915 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4916 or $EMERGENCY_MODE_48)
4917 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4918 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4919 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004920 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004921 {
4922 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4923 return correct_incharge($InfoId, $Version, $Mangled);
4924 }
4925 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004926 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004927 or not $BinaryOnly
4928 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004929 { # 1. --headers-only mode
4930 # 2. not mangled src-only symbols
4931 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4932 return $Mangled;
4933 }
4934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004935 }
4936 return "";
4937}
4938
4939sub setLanguage($$)
4940{
4941 my ($LibVersion, $Lang) = @_;
4942 if(not $UserLang) {
4943 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4944 }
4945}
4946
4947sub getSymbolInfo($)
4948{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004949 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004950 if(isInternal($InfoId)) {
4951 return;
4952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004953 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4954 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004955 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4956 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004957 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004958 return;
4959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004960 setFuncAccess($InfoId);
4961 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004962 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4963 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004964 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004965 return;
4966 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004968 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004969 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004970 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004971 if(not defined $TypeInfo{$Version}{$Return}
4972 or not $TypeInfo{$Version}{$Return}{"Name"})
4973 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004974 delete($SymbolInfo{$Version}{$InfoId});
4975 return;
4976 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004977 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004978 }
4979 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4980 {
4981 if(defined $MissedTypedef{$Version}{$Rid})
4982 {
4983 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4984 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4985 }
4986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004988 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4989 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004990 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004991 my $Orig = getFuncOrig($InfoId);
4992 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004993 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4994 {
4995 delete($SymbolInfo{$Version}{$InfoId});
4996 return;
4997 }
4998
4999 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005000 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005001 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005002 return;
5003 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005004
5005 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005006 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005007 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5008
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005009 my @TParams = getTParams($Orig, "Func");
5010 if(not @TParams)
5011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005012 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005013 return;
5014 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005015 foreach my $Pos (0 .. $#TParams)
5016 {
5017 my $Val = $TParams[$Pos];
5018 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5019
5020 if($Tmpl)
5021 {
5022 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5023 {
5024 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5025 }
5026 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005027 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005028
5029 if($Tmpl)
5030 {
5031 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5032 {
5033 if($Pos>$#TParams)
5034 {
5035 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5036 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5037 }
5038 }
5039 }
5040
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005041 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5042 { # operator<< <T>, operator>> <T>
5043 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5044 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005045 if(@TParams) {
5046 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5047 }
5048 else {
5049 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5050 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005051 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
5053 else
5054 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005055 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005056 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005057 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5058 {
5059 if($OSgroup eq "windows")
5060 { # cut the offset
5061 $MnglName=~s/\@\d+\Z//g;
5062 }
5063 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5064
5065 # NOTE: mangling of some symbols may change depending on GCC version
5066 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5067 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5068 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005069
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005070 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005071 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005073 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 return;
5075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005076 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005077 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005078 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005079 if($Skip)
5080 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005081 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005082 return;
5083 }
5084 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005085 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5086 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5087 }
5088
5089 if(set_Class_And_Namespace($InfoId))
5090 {
5091 delete($SymbolInfo{$Version}{$InfoId});
5092 return;
5093 }
5094
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005095 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5096 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005097 if(not defined $TypeInfo{$Version}{$ClassId}
5098 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5099 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005100 delete($SymbolInfo{$Version}{$InfoId});
5101 return;
5102 }
5103 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005104 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5105 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005106 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005107 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005108 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005109 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005110 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005111 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005112 }
5113 if($COMMON_LANGUAGE{$Version} eq "C++")
5114 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005115 # C++ or --headers-only mode
5116 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005118 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5119 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005122 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005123 if(my $Mangled = linkSymbol($InfoId)) {
5124 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 }
5126 }
5127 if($OStarget eq "windows")
5128 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005129 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005130 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005131 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005132 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005133 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005135 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 }
5137 }
5138 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005139 else
5140 { # not mangled in C
5141 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5142 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005143 if(not $CheckHeadersOnly
5144 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5145 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5146 {
5147 my $Incorrect = 0;
5148
5149 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5150 {
5151 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5152 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5153 { # mangled in the TU dump, but not mangled in the library
5154 $Incorrect = 1;
5155 }
5156 }
5157 else
5158 {
5159 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5160 { # all C++ functions are not mangled in the TU dump
5161 $Incorrect = 1;
5162 }
5163 }
5164 if($Incorrect)
5165 {
5166 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5167 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5168 }
5169 }
5170 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005171 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005172 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005173 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 return;
5175 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005176 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005177 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005178 { # identify virtual and pure virtual functions
5179 # NOTE: constructors cannot be virtual
5180 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5181 # in the TU dump, so taking it from the original symbol
5182 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5183 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5184 { # NOTE: D2 destructors are not present in a v-table
5185 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005188 if(isInline($InfoId)) {
5189 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005191 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005192 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005194 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5195 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005197 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005198 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005199 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005200 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005201 }
5202 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005203 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5204 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005205 if(not $ExtraDump)
5206 {
5207 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5208 { # non-target symbols
5209 delete($SymbolInfo{$Version}{$InfoId});
5210 return;
5211 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005213 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005214 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5215 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5216 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5217 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005218 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005219 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5220 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005221 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005222 return;
5223 }
5224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005225 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005226 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005227 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005229 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005230 return;
5231 }
5232 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005233 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 }
5235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5237 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5238 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005240 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5241 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 }
5247 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if(getFuncLink($InfoId) eq "Static") {
5249 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005251 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5252 {
5253 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5254 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005255 if($Unmangled=~/\.\_\d/)
5256 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005257 delete($SymbolInfo{$Version}{$InfoId});
5258 return;
5259 }
5260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005262
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5264 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5267 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005269
5270 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5271 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5272 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005273
5274 if($ExtraDump) {
5275 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5276 }
5277}
5278
5279sub guessHeader($)
5280{
5281 my $InfoId = $_[0];
5282 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5283 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5284 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5285 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5286 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5287 {
5288 if(get_filename($HPath) eq $Header)
5289 {
5290 my $HDir = get_filename(get_dirname($HPath));
5291 if($HDir ne "include"
5292 and $HDir=~/\A[a-z]+\Z/i) {
5293 return join_P($HDir, $Header);
5294 }
5295 }
5296 }
5297 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298}
5299
5300sub isInline($)
5301{ # "body: undefined" in the tree
5302 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005303 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5304 {
5305 if($Info=~/ undefined /i) {
5306 return 0;
5307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005308 }
5309 return 1;
5310}
5311
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005312sub hasThrow($)
5313{
5314 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5315 {
5316 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5317 return getTreeAttr_Unql($1, "unql");
5318 }
5319 }
5320 return 1;
5321}
5322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005323sub getTypeId($)
5324{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5326 {
5327 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5328 return $1;
5329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005330 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005331 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005332}
5333
5334sub setTypeMemb($$)
5335{
5336 my ($TypeId, $TypeAttr) = @_;
5337 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005338 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005339 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 if($TypeType eq "Enum")
5341 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005342 my $MInfoId = getTreeAttr_Csts($TypeId);
5343 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005344 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005345 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5346 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005347 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005348 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5349 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005350 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005351 }
5352 }
5353 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5354 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005355 my $MInfoId = getTreeAttr_Flds($TypeId);
5356 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005357 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005358 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5359 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005360 if(not $IType or $IType ne "field_decl")
5361 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005362
5363 if($IType eq "var_decl")
5364 { # static field
5365 $StaticFields = 1;
5366 }
5367
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005368 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005369 next;
5370 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005371 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005372 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005373 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005374 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005375 }
5376 if(not $StructMembName)
5377 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005378 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005379 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005380 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005381 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5382 if(isAnon($UnnamedTName))
5383 { # rename unnamed fields to unnamed0, unnamed1, ...
5384 $StructMembName = "unnamed".($UnnamedPos++);
5385 }
5386 }
5387 }
5388 if(not $StructMembName)
5389 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005390 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391 next;
5392 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005393 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005394 if(defined $MissedTypedef{$Version}{$MembTypeId})
5395 {
5396 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5397 $MembTypeId = $AddedTid;
5398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005399 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005400
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005401 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5402 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005403 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005404 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005405 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5406 }
5407 if($MInfo=~/spec:\s*mutable /)
5408 { # mutable fields
5409 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005411 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005412 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5413 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005415 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005416 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005417 }
5418 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005419 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005420 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5421 { # template
5422 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5423 }
5424 else {
5425 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005427 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005428
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005429 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005430 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005431 }
5432 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005433
5434 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005435}
5436
5437sub setFuncParams($)
5438{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005439 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005440 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005441
5442 my $FType = getFuncType($InfoId);
5443
5444 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005445 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005446 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5447 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005448 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005449 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005450 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5451 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005452 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005453 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005455 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005456 else
5457 { # skip
5458 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005459 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005460 # skip "this"-parameter
5461 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005463 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005464 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005465 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005466 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5467 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5468 if(not $ParamName)
5469 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005470 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005472 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5473 {
5474 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5475 $ParamTypeId = $AddedTid;
5476 }
5477 }
5478 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005479 if(not $PType or $PType eq "Unknown") {
5480 return 1;
5481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005482 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005483 if(not $PTName) {
5484 return 1;
5485 }
5486 if($PTName eq "void") {
5487 last;
5488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005489 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005490 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005491 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005492 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005493 $ParamInfoId = getNextElem($ParamInfoId);
5494 next;
5495 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005496 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005497
5498 if(my %Base = get_BaseType($ParamTypeId, $Version))
5499 {
5500 if(defined $Base{"Template"}) {
5501 return 1;
5502 }
5503 }
5504
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005505 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005506 if(my $Algn = getAlgn($ParamInfoId)) {
5507 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005509 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5510 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005511 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 }
5513 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005514 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005515 if($ParamName ne "this" or $FType ne "Method") {
5516 $PPos += 1;
5517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005518 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005519 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005520 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
5522 return 0;
5523}
5524
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005525sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005526{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005527 my ($InfoId, $Vtt_Pos) = @_;
5528 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005529 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005530 my $FType = getFuncType($InfoId);
5531
5532 if($FType eq "Method")
5533 {
5534 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005535 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 if(not $ParamListElemId)
5538 { # foo(...)
5539 return 1;
5540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005542 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005544 { # actual params: may differ from formal args
5545 # formal int*const
5546 # actual: int*
5547 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005548 {
5549 $Vtt_Pos=-1;
5550 $ParamListElemId = getNextElem($ParamListElemId);
5551 next;
5552 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005553 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5554 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005555 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005556 $HaveVoid = 1;
5557 last;
5558 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005559 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005560 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005561 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5562 {
5563 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5564 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5565 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005566 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005567 }
5568 }
5569 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5570 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005571 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005572 { # params
5573 if($OldId ne $ParamTypeId)
5574 {
5575 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5576 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5577
5578 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5580 }
5581 }
5582 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 }
5584 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005585 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005587 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5588 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005589 if($PurpType eq "nop_expr")
5590 { # func ( const char* arg = (const char*)(void*)0 )
5591 $PurpId = getTreeAttr_Op($PurpId);
5592 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005593 my $Val = getInitVal($PurpId, $ParamTypeId);
5594 if(defined $Val) {
5595 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005597 }
5598 }
5599 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005600 if($Pos!=0 or $FType ne "Method") {
5601 $PPos += 1;
5602 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005603 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005604 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005605 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005606}
5607
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005608sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005610 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5611 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005612 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5613 return $1;
5614 }
5615 }
5616 return "";
5617}
5618
5619sub getTreeAttr_Chain($)
5620{
5621 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5622 {
5623 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5624 return $1;
5625 }
5626 }
5627 return "";
5628}
5629
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005630sub getTreeAttr_Unql($)
5631{
5632 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5633 {
5634 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5635 return $1;
5636 }
5637 }
5638 return "";
5639}
5640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005641sub getTreeAttr_Scpe($)
5642{
5643 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5644 {
5645 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5646 return $1;
5647 }
5648 }
5649 return "";
5650}
5651
5652sub getTreeAttr_Type($)
5653{
5654 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5655 {
5656 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5657 return $1;
5658 }
5659 }
5660 return "";
5661}
5662
5663sub getTreeAttr_Name($)
5664{
5665 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5666 {
5667 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5668 return $1;
5669 }
5670 }
5671 return "";
5672}
5673
5674sub getTreeAttr_Mngl($)
5675{
5676 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5677 {
5678 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5679 return $1;
5680 }
5681 }
5682 return "";
5683}
5684
5685sub getTreeAttr_Prms($)
5686{
5687 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5688 {
5689 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5690 return $1;
5691 }
5692 }
5693 return "";
5694}
5695
5696sub getTreeAttr_Fncs($)
5697{
5698 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5699 {
5700 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5701 return $1;
5702 }
5703 }
5704 return "";
5705}
5706
5707sub getTreeAttr_Csts($)
5708{
5709 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5710 {
5711 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5712 return $1;
5713 }
5714 }
5715 return "";
5716}
5717
5718sub getTreeAttr_Purp($)
5719{
5720 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5721 {
5722 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5723 return $1;
5724 }
5725 }
5726 return "";
5727}
5728
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005729sub getTreeAttr_Op($)
5730{
5731 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5732 {
5733 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5734 return $1;
5735 }
5736 }
5737 return "";
5738}
5739
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005740sub getTreeAttr_Valu($)
5741{
5742 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5743 {
5744 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5745 return $1;
5746 }
5747 }
5748 return "";
5749}
5750
5751sub getTreeAttr_Flds($)
5752{
5753 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5754 {
5755 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5756 return $1;
5757 }
5758 }
5759 return "";
5760}
5761
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005762sub getTreeAttr_Binf($)
5763{
5764 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5765 {
5766 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5767 return $1;
5768 }
5769 }
5770 return "";
5771}
5772
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005773sub getTreeAttr_Args($)
5774{
5775 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5776 {
5777 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005778 return $1;
5779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005780 }
5781 return "";
5782}
5783
5784sub getTreeValue($)
5785{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005786 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5787 {
5788 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5789 return $1;
5790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005791 }
5792 return "";
5793}
5794
5795sub getTreeAccess($)
5796{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005797 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005798 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005799 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5800 {
5801 my $Access = $1;
5802 if($Access eq "prot") {
5803 return "protected";
5804 }
5805 elsif($Access eq "priv") {
5806 return "private";
5807 }
5808 }
5809 elsif($Info=~/ protected /)
5810 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005811 return "protected";
5812 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005813 elsif($Info=~/ private /)
5814 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005815 return "private";
5816 }
5817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005818 return "public";
5819}
5820
5821sub setFuncAccess($)
5822{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005823 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005824 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005825 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005826 }
5827 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005828 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005829 }
5830}
5831
5832sub setTypeAccess($$)
5833{
5834 my ($TypeId, $TypeAttr) = @_;
5835 my $Access = getTreeAccess($TypeId);
5836 if($Access eq "protected") {
5837 $TypeAttr->{"Protected"} = 1;
5838 }
5839 elsif($Access eq "private") {
5840 $TypeAttr->{"Private"} = 1;
5841 }
5842}
5843
5844sub setFuncKind($)
5845{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005846 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5847 {
5848 if($Info=~/pseudo tmpl/) {
5849 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5850 }
5851 elsif($Info=~/ constructor /) {
5852 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5853 }
5854 elsif($Info=~/ destructor /) {
5855 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005857 }
5858}
5859
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005860sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005861{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5863 {
5864 if($Info=~/spec[ ]*:[ ]*pure /) {
5865 return "PureVirt";
5866 }
5867 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5868 return "Virt";
5869 }
5870 elsif($Info=~/ pure\s+virtual /)
5871 { # support for old GCC versions
5872 return "PureVirt";
5873 }
5874 elsif($Info=~/ virtual /)
5875 { # support for old GCC versions
5876 return "Virt";
5877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005878 }
5879 return "";
5880}
5881
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005882sub getFuncLink($)
5883{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005884 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5885 {
5886 if($Info=~/link[ ]*:[ ]*static /) {
5887 return "Static";
5888 }
5889 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005890 return $1;
5891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005892 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005893 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005894}
5895
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005896sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005898 my ($Symbol, $LibVersion) = @_;
5899 return "" if(not $Symbol or not $LibVersion);
5900 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5901 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005902 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005903 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5904 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5905 }
5906 }
5907 if($NS)
5908 {
5909 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5910 return $NS;
5911 }
5912 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005914 while($NS=~s/::[^:]+\Z//)
5915 {
5916 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5917 return $NS;
5918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005919 }
5920 }
5921 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005922
5923 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924}
5925
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005926sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005927{
5928 my ($TypeName, $LibVersion) = @_;
5929 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005930 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005931 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005932 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5933 return $NS;
5934 }
5935 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937 while($NS=~s/::[^:]+\Z//)
5938 {
5939 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5940 return $NS;
5941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942 }
5943 }
5944 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005946}
5947
5948sub getNameSpace($)
5949{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005950 my $InfoId = $_[0];
5951 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005953 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005955 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005957 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5958 {
5959 my $NameSpace = getTreeStr($1);
5960 if($NameSpace eq "::")
5961 { # global namespace
5962 return "";
5963 }
5964 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5965 $NameSpace = $BaseNameSpace."::".$NameSpace;
5966 }
5967 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5968 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005969 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005970 else {
5971 return "";
5972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005974 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005975 { # inside data type
5976 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5977 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005980 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005981 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005982}
5983
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005984sub getEnumMembVal($)
5985{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005986 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005988 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5989 {
5990 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5991 {
5992 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5993 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5994 return getTreeValue($1);
5995 }
5996 else
5997 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
5998 return getTreeValue($1);
5999 }
6000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006001 }
6002 }
6003 return "";
6004}
6005
6006sub getSize($)
6007{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006008 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6009 {
6010 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6011 return getTreeValue($1);
6012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006013 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006014 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015}
6016
6017sub getAlgn($)
6018{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006019 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6020 {
6021 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6022 return $1;
6023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006025 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026}
6027
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006028sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6031 {
6032 if($Info=~/ bitfield /) {
6033 return getSize($_[0]);
6034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006036 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037}
6038
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006039sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006040{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006041 if(my $Chan = getTreeAttr_Chan($_[0])) {
6042 return $Chan;
6043 }
6044 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6045 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006047 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006048}
6049
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006050sub registerHeader($$)
6051{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006053 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054 return "";
6055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006056 if(is_abs($Header) and not -f $Header)
6057 { # incorrect absolute path
6058 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006060 if(skipHeader($Header, $LibVersion))
6061 { # skip
6062 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006064 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6065 {
6066 detect_header_includes($Header_Path, $LibVersion);
6067
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006068 if(defined $Tolerance and $Tolerance=~/3/)
6069 { # 3 - skip headers that include non-Linux headers
6070 if($OSgroup ne "windows")
6071 {
6072 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6073 {
6074 if(specificHeader($Inc, "windows")) {
6075 return "";
6076 }
6077 }
6078 }
6079 }
6080
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006081 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6082 { # redirect
6083 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6084 or skipHeader($RHeader_Path, $LibVersion))
6085 { # skip
6086 return "";
6087 }
6088 $Header_Path = $RHeader_Path;
6089 }
6090 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6091 { # skip
6092 return "";
6093 }
6094
6095 if(my $HName = get_filename($Header_Path))
6096 { # register
6097 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6098 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6099 }
6100
6101 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6102 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006103 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006104 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006105 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006106 }
6107
6108 if($CheckHeadersOnly
6109 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6110 { # /usr/include/c++/4.6.1/...
6111 $STDCXX_TESTING = 1;
6112 }
6113
6114 return $Header_Path;
6115 }
6116 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117}
6118
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006119sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120{
6121 my ($Dir, $WithDeps, $LibVersion) = @_;
6122 $Dir=~s/[\/\\]+\Z//g;
6123 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006127 if($WithDeps)
6128 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006129 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6130 return;
6131 }
6132 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6133 $Mode = "DepsOnly";
6134 }
6135 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006136 else
6137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006138 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6139 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6140 return;
6141 }
6142 }
6143 $Header_Dependency{$LibVersion}{$Dir} = 1;
6144 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6145 if($Mode eq "DepsOnly")
6146 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006147 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006148 $Header_Dependency{$LibVersion}{$Path} = 1;
6149 }
6150 return;
6151 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006152 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153 {
6154 if($WithDeps)
6155 {
6156 my $SubDir = $Path;
6157 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6158 { # register all sub directories
6159 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6160 }
6161 }
6162 next if(is_not_header($Path));
6163 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006165 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006166 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6167 }
6168 }
6169 if(get_filename($Dir) eq "include")
6170 { # search for "lib/include/" directory
6171 my $LibDir = $Dir;
6172 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006173 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006174 }
6175 }
6176}
6177
6178sub parse_redirect($$$)
6179{
6180 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006181 my @Errors = ();
6182 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6183 push(@Errors, $1);
6184 }
6185 my $Redirect = "";
6186 foreach (@Errors)
6187 {
6188 s/\s{2,}/ /g;
6189 if(/(only|must\ include
6190 |update\ to\ include
6191 |replaced\ with
6192 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006193 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006194 {
6195 $Redirect = $2;
6196 last;
6197 }
6198 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6199 {
6200 $Redirect = $2;
6201 last;
6202 }
6203 elsif(/this\ header\ should\ not\ be\ used
6204 |programs\ should\ not\ directly\ include
6205 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6206 |is\ not\ supported\ API\ for\ general\ use
6207 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006208 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6210 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6211 }
6212 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006213 if($Redirect)
6214 {
6215 $Redirect=~s/\A<//g;
6216 $Redirect=~s/>\Z//g;
6217 }
6218 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006219}
6220
6221sub parse_includes($$)
6222{
6223 my ($Content, $Path) = @_;
6224 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006225 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006226 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006227 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006228 my $Method = substr($Header, 0, 1, "");
6229 substr($Header, length($Header)-1, 1, "");
6230 $Header = path_format($Header, $OSgroup);
6231 if($Method eq "\"" or is_abs($Header))
6232 {
6233 if(-e join_P(get_dirname($Path), $Header))
6234 { # relative path exists
6235 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006236 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006237 else
6238 { # include "..." that doesn't exist is equal to include <...>
6239 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006241 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006242 else {
6243 $Includes{$Header} = 1;
6244 }
6245 }
6246 if($ExtraInfo)
6247 {
6248 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6249 { # FT_FREETYPE_H
6250 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006251 }
6252 }
6253 return \%Includes;
6254}
6255
6256sub ignore_path($)
6257{
6258 my $Path = $_[0];
6259 if($Path=~/\~\Z/)
6260 {# skipping system backup files
6261 return 1;
6262 }
6263 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6264 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6265 return 1;
6266 }
6267 return 0;
6268}
6269
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006270sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006271{
6272 my ($ArrRef, $W) = @_;
6273 return if(length($W)<2);
6274 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6275}
6276
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006277sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006278{
6279 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281 $H1=~s/\.[a-z]+\Z//ig;
6282 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006283
6284 my $Hname1 = get_filename($H1);
6285 my $Hname2 = get_filename($H2);
6286 my $HDir1 = get_dirname($H1);
6287 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006288 my $Dirname1 = get_filename($HDir1);
6289 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006290
6291 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6292 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6293
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006294 if($_[0] eq $_[1]
6295 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 return 0;
6297 }
6298 elsif($H1=~/\A\Q$H2\E/) {
6299 return 1;
6300 }
6301 elsif($H2=~/\A\Q$H1\E/) {
6302 return -1;
6303 }
6304 elsif($HDir1=~/\Q$Hname1\E/i
6305 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006306 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006307 return -1;
6308 }
6309 elsif($HDir2=~/\Q$Hname2\E/i
6310 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006311 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006312 return 1;
6313 }
6314 elsif($Hname1=~/\Q$Dirname1\E/i
6315 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006316 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006317 return -1;
6318 }
6319 elsif($Hname2=~/\Q$Dirname2\E/i
6320 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006321 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 return 1;
6323 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006324 elsif($Hname1=~/(config|lib|util)/i
6325 and $Hname2!~/(config|lib|util)/i)
6326 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006327 return -1;
6328 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006329 elsif($Hname2=~/(config|lib|util)/i
6330 and $Hname1!~/(config|lib|util)/i)
6331 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 return 1;
6333 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006334 else
6335 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006336 my $R1 = checkRelevance($H1);
6337 my $R2 = checkRelevance($H2);
6338 if($R1 and not $R2)
6339 { # libebook/e-book.h
6340 return -1;
6341 }
6342 elsif($R2 and not $R1)
6343 { # libebook/e-book.h
6344 return 1;
6345 }
6346 else
6347 {
6348 return (lc($H1) cmp lc($H2));
6349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350 }
6351}
6352
6353sub searchForHeaders($)
6354{
6355 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006357 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006358 registerGccHeaders();
6359
6360 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6361 { # c++ standard include paths
6362 registerCppHeaders();
6363 }
6364
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006365 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006366 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6367 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 {
6369 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006370 if($SystemRoot)
6371 {
6372 if(is_abs($Path)) {
6373 $Path = $SystemRoot.$Path;
6374 }
6375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006376 if(not -e $Path) {
6377 exitStatus("Access_Error", "can't access \'$Path\'");
6378 }
6379 elsif(-f $Path) {
6380 exitStatus("Access_Error", "\'$Path\' - not a directory");
6381 }
6382 elsif(-d $Path)
6383 {
6384 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006385 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006386 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6387 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006388 }
6389 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006390 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 }
6392 }
6393 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006394 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006395 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6396 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006398 # registering directories
6399 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6400 {
6401 next if(not -e $Path);
6402 $Path = get_abs_path($Path);
6403 $Path = path_format($Path, $OSgroup);
6404 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006405 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006406 }
6407 elsif(-f $Path)
6408 {
6409 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006410 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 and not $LocalIncludes{$Dir})
6412 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006413 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006414 # if(my $OutDir = get_dirname($Dir))
6415 # { # registering the outer directory
6416 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6417 # and not $LocalIncludes{$OutDir}) {
6418 # registerDir($OutDir, 0, $LibVersion);
6419 # }
6420 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 }
6422 }
6423 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006424
6425 # clean memory
6426 %RegisteredDirs = ();
6427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006428 # registering headers
6429 my $Position = 0;
6430 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6431 {
6432 if(is_abs($Dest) and not -e $Dest) {
6433 exitStatus("Access_Error", "can't access \'$Dest\'");
6434 }
6435 $Dest = path_format($Dest, $OSgroup);
6436 if(is_header($Dest, 1, $LibVersion))
6437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006438 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006439 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6440 }
6441 }
6442 elsif(-d $Dest)
6443 {
6444 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006445 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006446 {
6447 next if(ignore_path($Path));
6448 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006449 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450 push(@Registered, $HPath);
6451 }
6452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006453 @Registered = sort {sortHeaders($a, $b)} @Registered;
6454 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006455 foreach my $Path (@Registered) {
6456 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6457 }
6458 }
6459 else {
6460 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6461 }
6462 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006463
6464 if(defined $Tolerance and $Tolerance=~/4/)
6465 { # 4 - skip headers included by others
6466 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6467 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006468 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006469 delete($Registered_Headers{$LibVersion}{$Path});
6470 }
6471 }
6472 }
6473
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006474 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6475 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006476 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006477 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006478 if(is_abs($Header) and not -f $Header) {
6479 exitStatus("Access_Error", "can't access file \'$Header\'");
6480 }
6481 $Header = path_format($Header, $OSgroup);
6482 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6483 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006484 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006485 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006486 }
6487 else {
6488 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 }
6491 }
6492 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6493 { # set relative paths (for duplicates)
6494 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6495 { # search for duplicates
6496 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6497 my $Prefix = get_dirname($FirstPath);
6498 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6499 { # detect a shortest distinguishing prefix
6500 my $NewPrefix = $1;
6501 my %Identity = ();
6502 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6503 {
6504 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6505 $Identity{$Path} = $1;
6506 }
6507 }
6508 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006509 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006510 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6511 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6512 }
6513 last;
6514 }
6515 $Prefix = $NewPrefix; # increase prefix
6516 }
6517 }
6518 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006519
6520 # clean memory
6521 %HeaderName_Paths = ();
6522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006523 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6524 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006525 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006526 my ($Pos, $PairPos) = (-1, -1);
6527 my ($Path, $PairPath) = ();
6528 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6529 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6530 foreach my $Header_Path (@Paths)
6531 {
6532 if(get_filename($Header_Path) eq $PairName)
6533 {
6534 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6535 $PairPath = $Header_Path;
6536 }
6537 if(get_filename($Header_Path) eq $HeaderName)
6538 {
6539 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6540 $Path = $Header_Path;
6541 }
6542 }
6543 if($PairPos!=-1 and $Pos!=-1
6544 and int($PairPos)<int($Pos))
6545 {
6546 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6547 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6548 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6549 }
6550 }
6551 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6552 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6553 }
6554}
6555
6556sub detect_real_includes($$)
6557{
6558 my ($AbsPath, $LibVersion) = @_;
6559 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6560 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6561 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6562 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006564 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006566 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6567 return () if(not $Path);
6568 open(PREPROC, $Path);
6569 while(<PREPROC>)
6570 {
6571 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6572 {
6573 my $Include = path_format($1, $OSgroup);
6574 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6575 next;
6576 }
6577 if($Include eq $AbsPath) {
6578 next;
6579 }
6580 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6581 }
6582 }
6583 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006584 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6585}
6586
6587sub detect_header_includes($$)
6588{
6589 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006590 return if(not $LibVersion or not $Path);
6591 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6592 return;
6593 }
6594 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6595
6596 if(not -e $Path) {
6597 return;
6598 }
6599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006600 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006601 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6602 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006603 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006604 {
6605 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006606 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 }
6608 if($RedirectPath ne $Path) {
6609 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6610 }
6611 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006612 else
6613 { # can't find
6614 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006616 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006617 if(my $Inc = parse_includes($Content, $Path))
6618 {
6619 foreach my $Include (keys(%{$Inc}))
6620 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006621 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006622
6623 if(defined $Tolerance and $Tolerance=~/4/)
6624 {
6625 if(my $HPath = identifyHeader($Include, $LibVersion))
6626 {
6627 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6628 }
6629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006632}
6633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006634sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006635{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006636 my $Path = $_[0];
6637 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006638 if($OStarget eq "symbian")
6639 {
6640 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6641 { # epoc32/include/libc/{stdio, ...}.h
6642 return 1;
6643 }
6644 }
6645 else
6646 {
6647 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6648 { # /usr/include/{stdio, ...}.h
6649 return 1;
6650 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006652 return 0;
6653}
6654
6655sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006656{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006657 my $Dir = $_[0];
6658 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006659 if($OStarget eq "symbian")
6660 {
6661 if(get_filename($OutDir) eq "libc"
6662 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6663 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6664 return 1;
6665 }
6666 }
6667 else
6668 { # linux
6669 if($OutDir eq "/usr/include"
6670 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6671 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6672 return 1;
6673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006674 }
6675 return 0;
6676}
6677
6678sub detect_recursive_includes($$)
6679{
6680 my ($AbsPath, $LibVersion) = @_;
6681 return () if(not $AbsPath);
6682 if(isCyclical(\@RecurInclude, $AbsPath)) {
6683 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6684 }
6685 my ($AbsDir, $Name) = separate_path($AbsPath);
6686 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006687 { # system GLIBC internals
6688 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006689 }
6690 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6691 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6692 }
6693 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006694
6695 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6696 { # skip /usr/include/c++/*/ headers
6697 return () if(not $ExtraInfo);
6698 }
6699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006700 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006701 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006702 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 { # check "real" (non-"model") include paths
6704 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6705 pop(@RecurInclude);
6706 return @Paths;
6707 }
6708 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6709 detect_header_includes($AbsPath, $LibVersion);
6710 }
6711 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6712 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006713 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006714 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006715 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006717 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006718 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006719 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006720 }
6721 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006722 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006723 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006724 { # search for the nearest header
6725 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006726 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006727 if(-f $Candidate) {
6728 $HPath = $Candidate;
6729 }
6730 }
6731 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006732 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006733 }
6734 next if(not $HPath);
6735 if($HPath eq $AbsPath) {
6736 next;
6737 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006738
6739 if($Debug)
6740 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006741# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6742# {
6743# print STDERR "$AbsPath -> $HPath\n";
6744# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006745 }
6746
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006747 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6748 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 { # only include <...>, skip include "..." prefixes
6750 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6751 }
6752 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6753 {
6754 if($IncPath eq $AbsPath) {
6755 next;
6756 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006757 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6758 if($RIncType==-1)
6759 { # include "..."
6760 $RIncType = $IncType;
6761 }
6762 elsif($RIncType==2)
6763 {
6764 if($IncType!=-1) {
6765 $RIncType = $IncType;
6766 }
6767 }
6768 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006769 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6770 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6771 }
6772 }
6773 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6774 {
6775 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6776 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6777 { # distinguish math.h from glibc and math.h from the tested library
6778 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6779 last;
6780 }
6781 }
6782 }
6783 pop(@RecurInclude);
6784 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6785}
6786
6787sub find_in_framework($$$)
6788{
6789 my ($Header, $Framework, $LibVersion) = @_;
6790 return "" if(not $Header or not $Framework or not $LibVersion);
6791 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6792 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6793 }
6794 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6795 {
6796 if(get_filename($Dependency) eq $Framework
6797 and -f get_dirname($Dependency)."/".$Header) {
6798 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6799 }
6800 }
6801 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6802}
6803
6804sub find_in_defaults($)
6805{
6806 my $Header = $_[0];
6807 return "" if(not $Header);
6808 if(defined $Cache{"find_in_defaults"}{$Header}) {
6809 return $Cache{"find_in_defaults"}{$Header};
6810 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006811 foreach my $Dir (@DefaultIncPaths,
6812 @DefaultGccPaths,
6813 @DefaultCppPaths,
6814 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006815 {
6816 next if(not $Dir);
6817 if(-f $Dir."/".$Header) {
6818 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6819 }
6820 }
6821 return ($Cache{"find_in_defaults"}{$Header}="");
6822}
6823
6824sub cmp_paths($$)
6825{
6826 my ($Path1, $Path2) = @_;
6827 my @Parts1 = split(/[\/\\]/, $Path1);
6828 my @Parts2 = split(/[\/\\]/, $Path2);
6829 foreach my $Num (0 .. $#Parts1)
6830 {
6831 my $Part1 = $Parts1[$Num];
6832 my $Part2 = $Parts2[$Num];
6833 if($GlibcDir{$Part1}
6834 and not $GlibcDir{$Part2}) {
6835 return 1;
6836 }
6837 elsif($GlibcDir{$Part2}
6838 and not $GlibcDir{$Part1}) {
6839 return -1;
6840 }
6841 elsif($Part1=~/glib/
6842 and $Part2!~/glib/) {
6843 return 1;
6844 }
6845 elsif($Part1!~/glib/
6846 and $Part2=~/glib/) {
6847 return -1;
6848 }
6849 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6850 return $CmpRes;
6851 }
6852 }
6853 return 0;
6854}
6855
6856sub checkRelevance($)
6857{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006858 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006859 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006860
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006861 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006862 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006863 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006864
6865 my $Name = lc(get_filename($Path));
6866 my $Dir = lc(get_dirname($Path));
6867
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006868 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006869
6870 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006871 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006872 my $Len = length($Token);
6873 next if($Len<=1);
6874 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6875 { # include/evolution-data-server-1.4/libebook/e-book.h
6876 return 1;
6877 }
6878 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006879 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006880 return 1;
6881 }
6882 }
6883 return 0;
6884}
6885
6886sub checkFamily(@)
6887{
6888 my @Paths = @_;
6889 return 1 if($#Paths<=0);
6890 my %Prefix = ();
6891 foreach my $Path (@Paths)
6892 {
6893 if($SystemRoot) {
6894 $Path = cut_path_prefix($Path, $SystemRoot);
6895 }
6896 if(my $Dir = get_dirname($Path))
6897 {
6898 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6899 $Prefix{$Dir} += 1;
6900 $Prefix{get_dirname($Dir)} += 1;
6901 }
6902 }
6903 foreach (sort keys(%Prefix))
6904 {
6905 if(get_depth($_)>=3
6906 and $Prefix{$_}==$#Paths+1) {
6907 return 1;
6908 }
6909 }
6910 return 0;
6911}
6912
6913sub isAcceptable($$$)
6914{
6915 my ($Header, $Candidate, $LibVersion) = @_;
6916 my $HName = get_filename($Header);
6917 if(get_dirname($Header))
6918 { # with prefix
6919 return 1;
6920 }
6921 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6922 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6923 return 1;
6924 }
6925 if(checkRelevance($Candidate))
6926 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6927 return 1;
6928 }
6929 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6930 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6931 # /usr/include/qt4/Qt/qsslconfiguration.h
6932 return 1;
6933 }
6934 if($OStarget eq "symbian")
6935 {
6936 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6937 return 1;
6938 }
6939 }
6940 return 0;
6941}
6942
6943sub isRelevant($$$)
6944{ # disallow to search for "abstract" headers in too deep directories
6945 my ($Header, $Candidate, $LibVersion) = @_;
6946 my $HName = get_filename($Header);
6947 if($OStarget eq "symbian")
6948 {
6949 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6950 return 0;
6951 }
6952 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006953 if($OStarget ne "bsd")
6954 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006955 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6956 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6957 return 0;
6958 }
6959 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006960 if($OStarget ne "windows")
6961 {
6962 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6963 { # skip /usr/include/wine/msvcrt
6964 return 0;
6965 }
6966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006967 if(not get_dirname($Header)
6968 and $Candidate=~/[\/\\]wx[\/\\]/)
6969 { # do NOT search in system /wx/ directory
6970 # for headers without a prefix: sstream.h
6971 return 0;
6972 }
6973 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6974 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6975 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6976 return 0;
6977 }
6978 if($Candidate=~/[\/\\]asm-/
6979 and (my $Arch = getArch($LibVersion)) ne "unknown")
6980 { # arch-specific header files
6981 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6982 {# skip ../asm-arm/ if using x86 architecture
6983 return 0;
6984 }
6985 }
6986 my @Candidates = getSystemHeaders($HName, $LibVersion);
6987 if($#Candidates==1)
6988 { # unique header
6989 return 1;
6990 }
6991 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6992 if($#SCandidates==1)
6993 { # unique name
6994 return 1;
6995 }
6996 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
6997 if(get_depth($Candidate)-$SystemDepth>=5)
6998 { # abstract headers in too deep directories
6999 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7000 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7001 return 0;
7002 }
7003 }
7004 if($Header eq "parser.h"
7005 and $Candidate!~/\/libxml2\//)
7006 { # select parser.h from xml2 library
7007 return 0;
7008 }
7009 if(not get_dirname($Header)
7010 and keys(%{$SystemHeaders{$HName}})>=3)
7011 { # many headers with the same name
7012 # like thread.h included without a prefix
7013 if(not checkFamily(@Candidates)) {
7014 return 0;
7015 }
7016 }
7017 return 1;
7018}
7019
7020sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007021{ # cache function
7022 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7023 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7024 }
7025 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7026}
7027
7028sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007029{
7030 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007031 if(-f $Header) {
7032 return $Header;
7033 }
7034 if(is_abs($Header) and not -f $Header)
7035 { # incorrect absolute path
7036 return "";
7037 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007038 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007039 { # too abstract configuration headers
7040 return "";
7041 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007042 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007043 if($OSgroup ne "windows")
7044 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007045 if(defined $WinHeaders{lc($HName)}
7046 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007047 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007048 return "";
7049 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007050 }
7051 if($OSgroup ne "macos")
7052 {
7053 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007054 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007055 return "";
7056 }
7057 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007058
7059 if(defined $ObsoleteHeaders{$HName})
7060 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007061 return "";
7062 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007063 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7064 {
7065 if(defined $AlienHeaders{$HName}
7066 or defined $AlienHeaders{$Header})
7067 { # alien headers from other systems
7068 return "";
7069 }
7070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007071
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007072 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007073 { # search in default paths
7074 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007075 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007076 }
7077 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007078 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007079 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007080 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007081 }
7082 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7083 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7084 {
7085 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007086 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007087 }
7088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089 # error
7090 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091}
7092
7093sub getSystemHeaders($$)
7094{
7095 my ($Header, $LibVersion) = @_;
7096 my @Candidates = ();
7097 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7098 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007099 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007100 next;
7101 }
7102 push(@Candidates, $Candidate);
7103 }
7104 return @Candidates;
7105}
7106
7107sub cut_path_prefix($$)
7108{
7109 my ($Path, $Prefix) = @_;
7110 return $Path if(not $Prefix);
7111 $Prefix=~s/[\/\\]+\Z//;
7112 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7113 return $Path;
7114}
7115
7116sub is_default_include_dir($)
7117{
7118 my $Dir = $_[0];
7119 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007120 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007121}
7122
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007123sub identifyHeader($$)
7124{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007125 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007126 if(not $Header) {
7127 return "";
7128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007129 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007130 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7131 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007132 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007133 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007134}
7135
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007136sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137{ # search for header by absolute path, relative path or name
7138 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139 if(-f $Header)
7140 { # it's relative or absolute path
7141 return get_abs_path($Header);
7142 }
7143 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7144 and my $HeaderDir = find_in_defaults($Header))
7145 { # search for libc headers in the /usr/include
7146 # for non-libc target library before searching
7147 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007148 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149 }
7150 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7151 { # search in the target library paths
7152 return $Path;
7153 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007154 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 { # search in the internal GCC include paths
7156 return $DefaultGccHeader{$Header};
7157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007158 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007160 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007161 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007162 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163 { # search in the default G++ include paths
7164 return $DefaultCppHeader{$Header};
7165 }
7166 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7167 { # search everywhere in the system
7168 return $AnyPath;
7169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007170 elsif($OSgroup eq "macos")
7171 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7172 if(my $Dir = get_dirname($Header))
7173 {
7174 my $RelPath = "Headers\/".get_filename($Header);
7175 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007176 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007177 }
7178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007180 # cannot find anything
7181 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007182}
7183
7184sub getLocation($)
7185{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007186 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7187 {
7188 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007189 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007192 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193}
7194
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007195sub getNameByInfo($)
7196{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007197 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007198 {
7199 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7200 {
7201 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7202 {
7203 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7204 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007205 my $Str = $1;
7206 if($CppMode{$Version}
7207 and $Str=~/\Ac99_(.+)\Z/)
7208 {
7209 if($CppKeywords_A{$1}) {
7210 $Str=$1;
7211 }
7212 }
7213 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007214 }
7215 }
7216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007218 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007219}
7220
7221sub getTreeStr($)
7222{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007223 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007225 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7226 {
7227 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007228 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007229 and $Str=~/\Ac99_(.+)\Z/)
7230 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007231 if($CppKeywords_A{$1}) {
7232 $Str=$1;
7233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007234 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007235 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007238 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239}
7240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241sub getFuncShortName($)
7242{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007243 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007245 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007247 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007248 {
7249 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7250 {
7251 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7252 return "operator ".$RName;
7253 }
7254 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007255 }
7256 else
7257 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007258 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7259 {
7260 if(my $Ind = $Operator_Indication{$1}) {
7261 return "operator".$Ind;
7262 }
7263 elsif(not $UnknownOperator{$1})
7264 {
7265 printMsg("WARNING", "unknown operator $1");
7266 $UnknownOperator{$1} = 1;
7267 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007268 }
7269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007270 }
7271 else
7272 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007273 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7274 return getTreeStr($1);
7275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007276 }
7277 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007278 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279}
7280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281sub getFuncReturn($)
7282{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007283 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7284 {
7285 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7286 {
7287 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7288 return $1;
7289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007290 }
7291 }
7292 return "";
7293}
7294
7295sub getFuncOrig($)
7296{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7298 {
7299 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7300 return $1;
7301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007303 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007304}
7305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306sub unmangleArray(@)
7307{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007308 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309 { # MSVC mangling
7310 my $UndNameCmd = get_CmdPath("undname");
7311 if(not $UndNameCmd) {
7312 exitStatus("Not_Found", "can't find \"undname\"");
7313 }
7314 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007315 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 }
7317 else
7318 { # GCC mangling
7319 my $CppFiltCmd = get_CmdPath("c++filt");
7320 if(not $CppFiltCmd) {
7321 exitStatus("Not_Found", "can't find c++filt in PATH");
7322 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007323 if(not defined $CPPFILT_SUPPORT_FILE)
7324 {
7325 my $Info = `$CppFiltCmd -h 2>&1`;
7326 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7327 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007328 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007329 if($CPPFILT_SUPPORT_FILE)
7330 { # new versions of c++filt can take a file
7331 if($#_>$MAX_CPPFILT_FILE_SIZE)
7332 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7333 # this is fixed in the oncoming version of Binutils
7334 my @Half = splice(@_, 0, ($#_+1)/2);
7335 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007336 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007337 else
7338 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007339 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7340 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7341 if($?==139)
7342 { # segmentation fault
7343 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7344 }
7345 return split(/\n/, $Res);
7346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 }
7348 else
7349 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007350 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7351 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007352 my @Half = splice(@_, 0, ($#_+1)/2);
7353 return (unmangleArray(@Half), unmangleArray(@_))
7354 }
7355 else
7356 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007357 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007358 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7359 if($?==139)
7360 { # segmentation fault
7361 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7362 }
7363 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364 }
7365 }
7366 }
7367}
7368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007369sub get_ChargeLevel($$)
7370{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007371 my ($Symbol, $LibVersion) = @_;
7372 return "" if($Symbol!~/\A(_Z|\?)/);
7373 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7374 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007375 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007376 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007377 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007378 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379 return "[in-charge]";
7380 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007381 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007382 return "[not-in-charge]";
7383 }
7384 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007385 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007386 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007387 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 return "[in-charge]";
7389 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007390 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 return "[not-in-charge]";
7392 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007393 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 return "[in-charge-deleting]";
7395 }
7396 }
7397 }
7398 else
7399 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007400 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 return "[in-charge]";
7402 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007403 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 return "[not-in-charge]";
7405 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007406 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007407 return "[in-charge]";
7408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[not-in-charge]";
7411 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007412 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 return "[in-charge-deleting]";
7414 }
7415 }
7416 return "";
7417}
7418
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007419sub get_Signature_M($$)
7420{
7421 my ($Symbol, $LibVersion) = @_;
7422 my $Signature_M = $tr_name{$Symbol};
7423 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7424 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007425 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007426 }
7427 return $Signature_M;
7428}
7429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430sub get_Signature($$)
7431{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007432 my ($Symbol, $LibVersion) = @_;
7433 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7434 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007436 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007437 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007438
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007439 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7440 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007442 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7443 {
7444 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7445 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7446 $Signature .= "~";
7447 }
7448 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007450 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007451 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452 }
7453 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007454 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007455 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007456 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7457 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007459 else
7460 {
7461 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 }
7463 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007464 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 {
7466 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007467 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 if(not $ParamTypeName) {
7471 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7472 }
7473 foreach my $Typedef (keys(%ChangedTypedef))
7474 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007475 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7476 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7477 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007479 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7480 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007481 if($ParamName eq "this"
7482 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007483 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007484 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007485 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007486 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007487 }
7488 else {
7489 push(@ParamArray, $ParamTypeName);
7490 }
7491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007492 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7493 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007494 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007495 }
7496 else
7497 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007498 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007500 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007501 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007502 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007503 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7504 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007505 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007507 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7508 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007509 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007511 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7512 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007513 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007514 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 }
7516 }
7517 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007518 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007519 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 }
7521 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007522 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007524 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525}
7526
7527sub create_member_decl($$)
7528{
7529 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007530 if($TName=~/\([\*]+\)/)
7531 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007532 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7533 return $TName;
7534 }
7535 else
7536 {
7537 my @ArraySizes = ();
7538 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7539 push(@ArraySizes, $1);
7540 }
7541 return $TName." ".$Member.join("", @ArraySizes);
7542 }
7543}
7544
7545sub getFuncType($)
7546{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007547 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7548 {
7549 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7550 {
7551 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7552 {
7553 if($Type eq "method_type") {
7554 return "Method";
7555 }
7556 elsif($Type eq "function_type") {
7557 return "Function";
7558 }
7559 else {
7560 return "Other";
7561 }
7562 }
7563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007564 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007565 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566}
7567
7568sub getFuncTypeId($)
7569{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007570 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7571 {
7572 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7573 return $1;
7574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007576 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577}
7578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007579sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007580{ # "._N" or "$_N" in older GCC versions
7581 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582}
7583
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007584sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007585{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007586 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7587 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007588 }
7589
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007590 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007592 if($_[1] ne "S")
7593 {
7594 $N=~s/\A[ ]+//g;
7595 $N=~s/[ ]+\Z//g;
7596 $N=~s/[ ]{2,}/ /g;
7597 }
7598
7599 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007600
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007601 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007602
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007603 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7604 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007606 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007607
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007608 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007609
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007610 if($_[1] eq "S")
7611 {
7612 if(index($N, "operator")!=-1) {
7613 $N=~s/\b(operator[ ]*)> >/$1>>/;
7614 }
7615 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007617 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618}
7619
7620sub get_HeaderDeps($$)
7621{
7622 my ($AbsPath, $LibVersion) = @_;
7623 return () if(not $AbsPath or not $LibVersion);
7624 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7625 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7626 }
7627 my %IncDir = ();
7628 detect_recursive_includes($AbsPath, $LibVersion);
7629 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7630 {
7631 next if(not $HeaderPath);
7632 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7633 my $Dir = get_dirname($HeaderPath);
7634 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7635 {
7636 my $Dep = $Dir;
7637 if($Prefix)
7638 {
7639 if($OSgroup eq "windows")
7640 { # case insensitive seach on windows
7641 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7642 next;
7643 }
7644 }
7645 elsif($OSgroup eq "macos")
7646 { # seach in frameworks
7647 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7648 {
7649 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7650 {# frameworks
7651 my ($HFramework, $HName) = ($1, $2);
7652 $Dep = $HFramework;
7653 }
7654 else
7655 {# mismatch
7656 next;
7657 }
7658 }
7659 }
7660 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7661 { # Linux, FreeBSD
7662 next;
7663 }
7664 }
7665 if(not $Dep)
7666 { # nothing to include
7667 next;
7668 }
7669 if(is_default_include_dir($Dep))
7670 { # included by the compiler
7671 next;
7672 }
7673 if(get_depth($Dep)==1)
7674 { # too short
7675 next;
7676 }
7677 if(isLibcDir($Dep))
7678 { # do NOT include /usr/include/{sys,bits}
7679 next;
7680 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007681 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007682 }
7683 }
7684 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7685 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7686}
7687
7688sub sortIncPaths($$)
7689{
7690 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007691 if(not $ArrRef or $#{$ArrRef}<0) {
7692 return $ArrRef;
7693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007694 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7695 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007696 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697 return $ArrRef;
7698}
7699
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007700sub sortDeps($$$)
7701{
7702 if($Header_Dependency{$_[2]}{$_[0]}
7703 and not $Header_Dependency{$_[2]}{$_[1]}) {
7704 return 1;
7705 }
7706 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7707 and $Header_Dependency{$_[2]}{$_[1]}) {
7708 return -1;
7709 }
7710 return 0;
7711}
7712
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007713sub join_P($$)
7714{
7715 my $S = "/";
7716 if($OSgroup eq "windows") {
7717 $S = "\\";
7718 }
7719 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720}
7721
7722sub get_namespace_additions($)
7723{
7724 my $NameSpaces = $_[0];
7725 my ($Additions, $AddNameSpaceId) = ("", 1);
7726 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7727 {
7728 next if($SkipNameSpaces{$Version}{$NS});
7729 next if(not $NS or $NameSpaces->{$NS}==-1);
7730 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7731 next if($NS=~/\A__/i);
7732 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007733 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007734 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7735 my @NS_Parts = split(/::/, $NS);
7736 next if($#NS_Parts==-1);
7737 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7738 foreach my $NS_Part (@NS_Parts)
7739 {
7740 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7741 $TypeDecl_Suffix .= "}";
7742 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007743 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007744 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7745 $Additions.=" $TypeDecl\n $FuncDecl\n";
7746 $AddNameSpaceId+=1;
7747 }
7748 return $Additions;
7749}
7750
7751sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007752{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007753 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007754 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007755 if($Fmt eq "windows")
7756 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007757 $Path=~s/\//\\/g;
7758 $Path=lc($Path);
7759 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007760 else
7761 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007762 $Path=~s/\\/\//g;
7763 }
7764 return $Path;
7765}
7766
7767sub inc_opt($$)
7768{
7769 my ($Path, $Style) = @_;
7770 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007771 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007772 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007773 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007774 return "-I\"".path_format($Path, "unix")."\"";
7775 }
7776 elsif($OSgroup eq "macos"
7777 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007778 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007779 return "-F".esc(get_dirname($Path));
7780 }
7781 else {
7782 return "-I".esc($Path);
7783 }
7784 }
7785 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007786 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007787 }
7788 return "";
7789}
7790
7791sub platformSpecs($)
7792{
7793 my $LibVersion = $_[0];
7794 my $Arch = getArch($LibVersion);
7795 if($OStarget eq "symbian")
7796 { # options for GCCE compiler
7797 my %Symbian_Opts = map {$_=>1} (
7798 "-D__GCCE__",
7799 "-DUNICODE",
7800 "-fexceptions",
7801 "-D__SYMBIAN32__",
7802 "-D__MARM_INTERWORK__",
7803 "-D_UNICODE",
7804 "-D__S60_50__",
7805 "-D__S60_3X__",
7806 "-D__SERIES60_3X__",
7807 "-D__EPOC32__",
7808 "-D__MARM__",
7809 "-D__EABI__",
7810 "-D__MARM_ARMV5__",
7811 "-D__SUPPORT_CPP_EXCEPTIONS__",
7812 "-march=armv5t",
7813 "-mapcs",
7814 "-mthumb-interwork",
7815 "-DEKA2",
7816 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7817 );
7818 return join(" ", keys(%Symbian_Opts));
7819 }
7820 elsif($OSgroup eq "windows"
7821 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7822 { # add options to MinGW compiler
7823 # to simulate the MSVC compiler
7824 my %MinGW_Opts = map {$_=>1} (
7825 "-D_WIN32",
7826 "-D_STDCALL_SUPPORTED",
7827 "-D__int64=\"long long\"",
7828 "-D__int32=int",
7829 "-D__int16=short",
7830 "-D__int8=char",
7831 "-D__possibly_notnullterminated=\" \"",
7832 "-D__nullterminated=\" \"",
7833 "-D__nullnullterminated=\" \"",
7834 "-D__w64=\" \"",
7835 "-D__ptr32=\" \"",
7836 "-D__ptr64=\" \"",
7837 "-D__forceinline=inline",
7838 "-D__inline=inline",
7839 "-D__uuidof(x)=IID()",
7840 "-D__try=",
7841 "-D__except(x)=",
7842 "-D__declspec(x)=__attribute__((x))",
7843 "-D__pragma(x)=",
7844 "-D_inline=inline",
7845 "-D__forceinline=__inline",
7846 "-D__stdcall=__attribute__((__stdcall__))",
7847 "-D__cdecl=__attribute__((__cdecl__))",
7848 "-D__fastcall=__attribute__((__fastcall__))",
7849 "-D__thiscall=__attribute__((__thiscall__))",
7850 "-D_stdcall=__attribute__((__stdcall__))",
7851 "-D_cdecl=__attribute__((__cdecl__))",
7852 "-D_fastcall=__attribute__((__fastcall__))",
7853 "-D_thiscall=__attribute__((__thiscall__))",
7854 "-DSHSTDAPI_(x)=x",
7855 "-D_MSC_EXTENSIONS",
7856 "-DSECURITY_WIN32",
7857 "-D_MSC_VER=1500",
7858 "-D_USE_DECLSPECS_FOR_SAL",
7859 "-D__noop=\" \"",
7860 "-DDECLSPEC_DEPRECATED=\" \"",
7861 "-D__builtin_alignof(x)=__alignof__(x)",
7862 "-DSORTPP_PASS");
7863 if($Arch eq "x86") {
7864 $MinGW_Opts{"-D_M_IX86=300"}=1;
7865 }
7866 elsif($Arch eq "x86_64") {
7867 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7868 }
7869 elsif($Arch eq "ia64") {
7870 $MinGW_Opts{"-D_M_IA64=300"}=1;
7871 }
7872 return join(" ", keys(%MinGW_Opts));
7873 }
7874 return "";
7875}
7876
7877my %C_Structure = map {$_=>1} (
7878# FIXME: Can't separate union and struct data types before dumping,
7879# so it sometimes cause compilation errors for unknown reason
7880# when trying to declare TYPE* tmp_add_class_N
7881# This is a list of such structures + list of other C structures
7882 "sigval",
7883 "sigevent",
7884 "sigaction",
7885 "sigvec",
7886 "sigstack",
7887 "timeval",
7888 "timezone",
7889 "rusage",
7890 "rlimit",
7891 "wait",
7892 "flock",
7893 "stat",
7894 "_stat",
7895 "stat32",
7896 "_stat32",
7897 "stat64",
7898 "_stat64",
7899 "_stati64",
7900 "if_nameindex",
7901 "usb_device",
7902 "sigaltstack",
7903 "sysinfo",
7904 "timeLocale",
7905 "tcp_debug",
7906 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007907 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007908 "timespec",
7909 "random_data",
7910 "drand48_data",
7911 "_IO_marker",
7912 "_IO_FILE",
7913 "lconv",
7914 "sched_param",
7915 "tm",
7916 "itimerspec",
7917 "_pthread_cleanup_buffer",
7918 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007919 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007920 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007921 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007922 "sigcontext",
7923 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007924 # Mac
7925 "_timex",
7926 "_class_t",
7927 "_category_t",
7928 "_class_ro_t",
7929 "_protocol_t",
7930 "_message_ref_t",
7931 "_super_message_ref_t",
7932 "_ivar_t",
7933 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007934);
7935
7936sub getCompileCmd($$$)
7937{
7938 my ($Path, $Opt, $Inc) = @_;
7939 my $GccCall = $GCC_PATH;
7940 if($Opt) {
7941 $GccCall .= " ".$Opt;
7942 }
7943 $GccCall .= " -x ";
7944 if($OSgroup eq "macos") {
7945 $GccCall .= "objective-";
7946 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007947
7948 if($EMERGENCY_MODE_48)
7949 { # workaround for GCC 4.8 (C only)
7950 $GccCall .= "c++";
7951 }
7952 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 { # compile as "C++" header
7954 # to obtain complete dump using GCC 4.0
7955 $GccCall .= "c++-header";
7956 }
7957 else
7958 { # compile as "C++" source
7959 # GCC 3.3 cannot compile headers
7960 $GccCall .= "c++";
7961 }
7962 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007963 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007964 $GccCall .= " ".$Opts;
7965 }
7966 # allow extra qualifications
7967 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007968 $GccCall .= " -fpermissive";
7969 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007970 if($NoStdInc)
7971 {
7972 $GccCall .= " -nostdinc";
7973 $GccCall .= " -nostdinc++";
7974 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007975 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007976 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007977 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007979 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007980 if($Inc)
7981 { # include paths
7982 $GccCall .= " ".$Inc;
7983 }
7984 return $GccCall;
7985}
7986
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007987sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007988{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007989 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007990 my %HeaderElems = (
7991 # Types
7992 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007993 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007994 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7995 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007996 "time.h" => ["time_t"],
7997 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007998 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7999 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008000 "stdbool.h" => ["_Bool"],
8001 "rpc/xdr.h" => ["bool_t"],
8002 "in_systm.h" => ["n_long", "n_short"],
8003 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008004 "arpa/inet.h" => ["fw_src", "ip_src"],
8005 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008006 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008007 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008008 );
8009 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008010 foreach (keys(%HeaderElems))
8011 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008012 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008013 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008014 }
8015 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008016 my %Types = ();
8017 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8018 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008019 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008020 }
8021 if(keys(%Types))
8022 {
8023 my %AddHeaders = ();
8024 foreach my $Type (keys(%Types))
8025 {
8026 if(my $Header = $AutoPreamble{$Type})
8027 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008028 if(my $Path = identifyHeader($Header, $LibVersion))
8029 {
8030 if(skipHeader($Path, $LibVersion)) {
8031 next;
8032 }
8033 $Path = path_format($Path, $OSgroup);
8034 $AddHeaders{$Path}{"Type"} = $Type;
8035 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008036 }
8037 }
8038 }
8039 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008040 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008041 }
8042 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008043 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008044}
8045
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008046sub checkCTags($)
8047{
8048 my $Path = $_[0];
8049 if(not $Path) {
8050 return;
8051 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008052 my $CTags = undef;
8053
8054 if($OSgroup eq "bsd")
8055 { # use ectags on BSD
8056 $CTags = get_CmdPath("ectags");
8057 if(not $CTags) {
8058 printMsg("WARNING", "can't find \'ectags\' program");
8059 }
8060 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008061 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008062 $CTags = get_CmdPath("ctags");
8063 }
8064 if(not $CTags)
8065 {
8066 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008067 return;
8068 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008069
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008070 if($OSgroup ne "linux")
8071 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008072 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8073 if($Info!~/exuberant/i)
8074 {
8075 printMsg("WARNING", "incompatible version of \'ctags\' program");
8076 return;
8077 }
8078 }
8079
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008080 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008081 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008082 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008083 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008084 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008085 open(CTAGS, "<", $Out);
8086 while(my $Line = <CTAGS>)
8087 {
8088 chomp($Line);
8089 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008090 if(defined $Intrinsic_Keywords{$Name})
8091 { # noise
8092 next;
8093 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008094 if($Type eq "n")
8095 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008096 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008097 next;
8098 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008099 if(index($Scpe, "struct:")==0) {
8100 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008101 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008102 if(index($Scpe, "namespace:")==0)
8103 {
8104 if($Scpe=~s/\Anamespace://) {
8105 $Name = $Scpe."::".$Name;
8106 }
8107 }
8108 $TUnit_NameSpaces{$Version}{$Name} = 1;
8109 }
8110 elsif($Type eq "p")
8111 {
8112 if(not $Scpe or index($Scpe, "namespace:")==0) {
8113 $TUnit_Funcs{$Version}{$Name} = 1;
8114 }
8115 }
8116 elsif($Type eq "x")
8117 {
8118 if(not $Scpe or index($Scpe, "namespace:")==0) {
8119 $TUnit_Vars{$Version}{$Name} = 1;
8120 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008121 }
8122 }
8123 close(CTAGS);
8124}
8125
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008126sub preChange($$)
8127{
8128 my ($HeaderPath, $IncStr) = @_;
8129
8130 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8131 my $Content = undef;
8132
8133 if($OStarget eq "windows"
8134 and get_dumpmachine($GCC_PATH)=~/mingw/i
8135 and $MinGWMode{$Version}!=-1)
8136 { # modify headers to compile by MinGW
8137 if(not $Content)
8138 { # preprocessing
8139 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8140 }
8141 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8142 { # __asm { ... }
8143 $MinGWMode{$Version}=1;
8144 }
8145 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8146 { # comments after preprocessing
8147 $MinGWMode{$Version}=1;
8148 }
8149 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8150 { # 0xffui8
8151 $MinGWMode{$Version}=1;
8152 }
8153
8154 if($MinGWMode{$Version}) {
8155 printMsg("INFO", "Using MinGW compatibility mode");
8156 }
8157 }
8158
8159 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8160 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8161 { # rename C++ keywords in C code
8162 # disable this code by -cpp-compatible option
8163 if(not $Content)
8164 { # preprocessing
8165 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8166 }
8167 my $RegExp_C = join("|", keys(%CppKeywords_C));
8168 my $RegExp_F = join("|", keys(%CppKeywords_F));
8169 my $RegExp_O = join("|", keys(%CppKeywords_O));
8170
8171 my $Detected = undef;
8172
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008173 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 +04008174 { # MATCH:
8175 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008176 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008177 # unsigned private: 8;
8178 # DO NOT MATCH:
8179 # #pragma GCC visibility push(default)
8180 $CppMode{$Version} = 1;
8181 $Detected = "$1$2$3$4" if(not defined $Detected);
8182 }
8183 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8184 { # MATCH:
8185 # int delete(...);
8186 # int explicit(...);
8187 # DO NOT MATCH:
8188 # void operator delete(...)
8189 $CppMode{$Version} = 1;
8190 $Detected = "$1$2$3" if(not defined $Detected);
8191 }
8192 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8193 { # MATCH:
8194 # int bool;
8195 # DO NOT MATCH:
8196 # bool X;
8197 # return *this;
8198 # throw;
8199 $CppMode{$Version} = 1;
8200 $Detected = "$1$2$3" if(not defined $Detected);
8201 }
8202 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8203 { # MATCH:
8204 # int operator(...);
8205 # DO NOT MATCH:
8206 # int operator()(...);
8207 $CppMode{$Version} = 1;
8208 $Detected = "$1$2$3" if(not defined $Detected);
8209 }
8210 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8211 { # MATCH:
8212 # int foo(int operator);
8213 # int foo(int operator, int other);
8214 # DO NOT MATCH:
8215 # int operator,(...);
8216 $CppMode{$Version} = 1;
8217 $Detected = "$1$2$3" if(not defined $Detected);
8218 }
8219 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8220 { # MATCH:
8221 # int foo(gboolean *bool);
8222 # DO NOT MATCH:
8223 # void setTabEnabled(int index, bool);
8224 $CppMode{$Version} = 1;
8225 $Detected = "$1$2$3" if(not defined $Detected);
8226 }
8227 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8228 { # MATCH:
8229 # int foo(int* this);
8230 # int bar(int this);
8231 # int baz(int throw);
8232 # DO NOT MATCH:
8233 # foo(X, this);
8234 $CppMode{$Version} = 1;
8235 $Detected = "$1$2$3$4" if(not defined $Detected);
8236 }
8237 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8238 { # MATCH:
8239 # struct template {...};
8240 # extern template foo(...);
8241 $CppMode{$Version} = 1;
8242 $Detected = "$1$2" if(not defined $Detected);
8243 }
8244
8245 if($CppMode{$Version} == 1)
8246 {
8247 if($Debug)
8248 {
8249 $Detected=~s/\A\s+//g;
8250 printMsg("INFO", "Detected code: \"$Detected\"");
8251 }
8252 }
8253
8254 # remove typedef enum NAME NAME;
8255 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8256 my $N = 0;
8257 while($N<=$#FwdTypedefs-1)
8258 {
8259 my $S = $FwdTypedefs[$N];
8260 if($S eq $FwdTypedefs[$N+1])
8261 {
8262 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008263 $CppMode{$Version} = 1;
8264
8265 if($Debug) {
8266 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8267 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008268 }
8269 $N+=2;
8270 }
8271
8272 if($CppMode{$Version}==1) {
8273 printMsg("INFO", "Using C++ compatibility mode");
8274 }
8275 }
8276
8277 if($CppMode{$Version}==1
8278 or $MinGWMode{$Version}==1)
8279 {
8280 my $IPath = $TMP_DIR."/dump$Version.i";
8281 writeFile($IPath, $Content);
8282 return $IPath;
8283 }
8284
8285 return undef;
8286}
8287
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008288sub getDump()
8289{
8290 if(not $GCC_PATH) {
8291 exitStatus("Error", "internal error - GCC path is not set");
8292 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008293
8294 my @Headers = keys(%{$Registered_Headers{$Version}});
8295 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8296
8297 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8298
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008299 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008300 my $HeaderPath = $TmpHeaderPath;
8301
8302 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008303 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008304 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8305 {
8306 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008307 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008308 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008309 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008310 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8311 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008312 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008313 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008314 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008315 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8316 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008318 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008319 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008320
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008321 if($ExtraInfo)
8322 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008323 if($IncludeString) {
8324 writeFile($ExtraInfo."/include-string", $IncludeString);
8325 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008326 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8327 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008328
8329 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8330 {
8331 my $REDIR = "";
8332 foreach my $P1 (sort @Redirects) {
8333 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8334 }
8335 writeFile($ExtraInfo."/include-redirect", $REDIR);
8336 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008337 }
8338
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008339 if(not keys(%{$TargetHeaders{$Version}}))
8340 { # Target headers
8341 addTargetHeaders($Version);
8342 }
8343
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008344 # clean memory
8345 %RecursiveIncludes = ();
8346 %Header_Include_Prefix = ();
8347 %Header_Includes = ();
8348
8349 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008350 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008351 delete($Cache{"detect_header_includes"});
8352 delete($Cache{"selectSystemHeader"});
8353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008354 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008355 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8356 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008357
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008358 if($ExtraInfo)
8359 { # extra information for other tools
8360 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8361 }
8362
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008363 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008364 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008365 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008366
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008367 if($COMMON_LANGUAGE{$Version} eq "C++") {
8368 checkCTags($Pre);
8369 }
8370
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008371 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8372 { # try to correct the preprocessor output
8373 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008374 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008376 if($COMMON_LANGUAGE{$Version} eq "C++")
8377 { # add classes and namespaces to the dump
8378 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008379 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008380 or $MinGWMode{$Version}==1) {
8381 $CHdump .= " -fpreprocessed";
8382 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008383 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008384 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008385 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008386 chdir($ORIG_DIR);
8387 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8388 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008389 my $Content = readFile($ClassDump);
8390 foreach my $ClassInfo (split(/\n\n/, $Content))
8391 {
8392 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8393 {
8394 my $CName = $1;
8395 next if($CName=~/\A(__|_objc_|_opaque_)/);
8396 $TUnit_NameSpaces{$Version}{$CName} = -1;
8397 if($CName=~/\A[\w:]+\Z/)
8398 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008399 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008400 }
8401 if($CName=~/(\w[\w:]*)::/)
8402 { # namespaces
8403 my $NS = $1;
8404 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8405 $TUnit_NameSpaces{$Version}{$NS} = 1;
8406 }
8407 }
8408 }
8409 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8410 { # read v-tables (advanced approach)
8411 my ($CName, $VTable) = ($1, $2);
8412 $ClassVTable_Content{$Version}{$CName} = $VTable;
8413 }
8414 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008415 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8416 { # add user-defined namespaces
8417 $TUnit_NameSpaces{$Version}{$NS} = 1;
8418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008419 if($Debug)
8420 { # debug mode
8421 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008422 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008423 }
8424 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008425 }
8426
8427 # add namespaces and classes
8428 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8429 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008430 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008431 }
8432 # some GCC versions don't include class methods to the TU dump by default
8433 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008434 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008435 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8436 {
8437 next if($C_Structure{$CName});
8438 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008439 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008440 if(not $Force and $GCC_44
8441 and $OSgroup eq "linux")
8442 { # optimization for linux with GCC >= 4.4
8443 # disable this code by -force option
8444 if(index($CName, "::")!=-1)
8445 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008446 next;
8447 }
8448 }
8449 else
8450 {
8451 if($CName=~/\A(.+)::[^:]+\Z/
8452 and $TUnit_Classes{$Version}{$1})
8453 { # classes inside other classes
8454 next;
8455 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008457 if(defined $TUnit_Funcs{$Version}{$CName})
8458 { # the same name for a function and type
8459 next;
8460 }
8461 if(defined $TUnit_Vars{$Version}{$CName})
8462 { # the same name for a variable and type
8463 next;
8464 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008465 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8466 }
8467 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008468 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008469 }
8470 }
8471 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8472 # create TU dump
8473 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008474 if($UserLang eq "C") {
8475 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8476 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008477 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008478 or $MinGWMode{$Version}==1) {
8479 $TUdump .= " -fpreprocessed";
8480 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008481 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008482 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8483 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008484 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008485 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008486 if($?)
8487 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008488 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008489 { # try to recompile
8490 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008491 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008492 and index($Errors, "c99_")!=-1
8493 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008494 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008495 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008496
8497 if($Debug)
8498 {
8499 # printMsg("INFO", $Errors);
8500 }
8501
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008502 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008503 resetLogging($Version);
8504 $TMP_DIR = tempdir(CLEANUP=>1);
8505 return getDump();
8506 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008507 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008508 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008509 { # add auto preamble headers and try again
8510 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008511 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008512 foreach my $Num (0 .. $#Headers)
8513 {
8514 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008515 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8516 {
8517 push_U($Include_Preamble{$Version}, $Path);
8518 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008519 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008520 }
8521 resetLogging($Version);
8522 $TMP_DIR = tempdir(CLEANUP=>1);
8523 return getDump();
8524 }
8525 elsif($Cpp0xMode{$Version}!=-1
8526 and ($Errors=~/\Q-std=c++0x\E/
8527 or $Errors=~/is not a class or namespace/))
8528 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008529 if(check_gcc($GCC_PATH, "4.6"))
8530 {
8531 $Cpp0xMode{$Version}=-1;
8532 printMsg("INFO", "Enabling c++0x mode");
8533 resetLogging($Version);
8534 $TMP_DIR = tempdir(CLEANUP=>1);
8535 $CompilerOptions{$Version} .= " -std=c++0x";
8536 return getDump();
8537 }
8538 else {
8539 printMsg("WARNING", "Probably c++0x construction detected");
8540 }
8541
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008542 }
8543 elsif($MinGWMode{$Version}==1)
8544 { # disable MinGW mode and try again
8545 $MinGWMode{$Version}=-1;
8546 resetLogging($Version);
8547 $TMP_DIR = tempdir(CLEANUP=>1);
8548 return getDump();
8549 }
8550 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008551 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008552 else {
8553 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008555 printMsg("ERROR", "some errors occurred when compiling headers");
8556 printErrorLog($Version);
8557 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008558 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008559 }
8560 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008561 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008562 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008563
8564 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8565 return $TUs[0];
8566 }
8567 else
8568 {
8569 my $Msg = "can't compile header(s)";
8570 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8571 $Msg .= "\nDid you install G++?";
8572 }
8573 exitStatus("Cannot_Compile", $Msg);
8574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008575}
8576
8577sub cmd_file($)
8578{
8579 my $Path = $_[0];
8580 return "" if(not $Path or not -e $Path);
8581 if(my $CmdPath = get_CmdPath("file")) {
8582 return `$CmdPath -b \"$Path\"`;
8583 }
8584 return "";
8585}
8586
8587sub getIncString($$)
8588{
8589 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008590 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008591 my $String = "";
8592 foreach (@{$ArrRef}) {
8593 $String .= " ".inc_opt($_, $Style);
8594 }
8595 return $String;
8596}
8597
8598sub getIncPaths(@)
8599{
8600 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008601 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008602 if($INC_PATH_AUTODETECT{$Version})
8603 { # auto-detecting dependencies
8604 my %Includes = ();
8605 foreach my $HPath (@HeaderPaths)
8606 {
8607 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8608 {
8609 if($Skip_Include_Paths{$Version}{$Dir}) {
8610 next;
8611 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008612 if($SystemRoot)
8613 {
8614 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8615 next;
8616 }
8617 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008618 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008619 }
8620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008621 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008622 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008623 }
8624 }
8625 else
8626 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008627 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008628 }
8629 return \@IncPaths;
8630}
8631
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008632sub push_U($@)
8633{ # push unique
8634 if(my $Array = shift @_)
8635 {
8636 if(@_)
8637 {
8638 my %Exist = map {$_=>1} @{$Array};
8639 foreach my $Elem (@_)
8640 {
8641 if(not defined $Exist{$Elem})
8642 {
8643 push(@{$Array}, $Elem);
8644 $Exist{$Elem} = 1;
8645 }
8646 }
8647 }
8648 }
8649}
8650
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008651sub callPreprocessor($$$)
8652{
8653 my ($Path, $Inc, $LibVersion) = @_;
8654 return "" if(not $Path or not -f $Path);
8655 my $IncludeString=$Inc;
8656 if(not $Inc) {
8657 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8658 }
8659 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008660 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008661 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008662 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663}
8664
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008665sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008666{ # native "find" is much faster than File::Find (~6x)
8667 # also the File::Find doesn't support --maxdepth N option
8668 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008669 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670 return () if(not $Path or not -e $Path);
8671 if($OSgroup eq "windows")
8672 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 $Path = get_abs_path($Path);
8674 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008675 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008676 if($MaxDepth!=1) {
8677 $Cmd .= " /S";
8678 }
8679 if($Type eq "d") {
8680 $Cmd .= " /AD";
8681 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008682 elsif($Type eq "f") {
8683 $Cmd .= " /A-D";
8684 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008685 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008686 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008687 {
8688 if(not $UseRegex)
8689 { # FIXME: how to search file names in MS shell?
8690 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008691 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008692 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008694 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 }
8696 my @AbsPaths = ();
8697 foreach my $File (@Files)
8698 {
8699 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008700 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008701 }
8702 if($Type eq "f" and not -f $File)
8703 { # skip dirs
8704 next;
8705 }
8706 push(@AbsPaths, path_format($File, $OSgroup));
8707 }
8708 if($Type eq "d") {
8709 push(@AbsPaths, $Path);
8710 }
8711 return @AbsPaths;
8712 }
8713 else
8714 {
8715 my $FindCmd = get_CmdPath("find");
8716 if(not $FindCmd) {
8717 exitStatus("Not_Found", "can't find a \"find\" command");
8718 }
8719 $Path = get_abs_path($Path);
8720 if(-d $Path and -l $Path
8721 and $Path!~/\/\Z/)
8722 { # for directories that are symlinks
8723 $Path.="/";
8724 }
8725 my $Cmd = $FindCmd." \"$Path\"";
8726 if($MaxDepth) {
8727 $Cmd .= " -maxdepth $MaxDepth";
8728 }
8729 if($Type) {
8730 $Cmd .= " -type $Type";
8731 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008732 if($Name and not $UseRegex)
8733 { # wildcards
8734 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008736 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008737 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008738 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8739 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008740 my @Files = split(/\n/, $Res);
8741 if($Name and $UseRegex)
8742 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008743 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008744 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008745 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008746 }
8747}
8748
8749sub unpackDump($)
8750{
8751 my $Path = $_[0];
8752 return "" if(not $Path or not -e $Path);
8753 $Path = get_abs_path($Path);
8754 $Path = path_format($Path, $OSgroup);
8755 my ($Dir, $FileName) = separate_path($Path);
8756 my $UnpackDir = $TMP_DIR."/unpack";
8757 rmtree($UnpackDir);
8758 mkpath($UnpackDir);
8759 if($FileName=~s/\Q.zip\E\Z//g)
8760 { # *.zip
8761 my $UnzipCmd = get_CmdPath("unzip");
8762 if(not $UnzipCmd) {
8763 exitStatus("Not_Found", "can't find \"unzip\" command");
8764 }
8765 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008766 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008767 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008768 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769 }
8770 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008771 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 if(not @Contents) {
8773 exitStatus("Error", "can't extract \'$Path\'");
8774 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008775 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008777 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008778 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008779 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008780 if($OSgroup eq "windows")
8781 { # -xvzf option is not implemented in tar.exe (2003)
8782 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8783 my $TarCmd = get_CmdPath("tar");
8784 if(not $TarCmd) {
8785 exitStatus("Not_Found", "can't find \"tar\" command");
8786 }
8787 my $GzipCmd = get_CmdPath("gzip");
8788 if(not $GzipCmd) {
8789 exitStatus("Not_Found", "can't find \"gzip\" command");
8790 }
8791 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008792 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008793 if($?) {
8794 exitStatus("Error", "can't extract \'$Path\'");
8795 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008796 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008797 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008798 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008799 }
8800 chdir($ORIG_DIR);
8801 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008802 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008803 if(not @Contents) {
8804 exitStatus("Error", "can't extract \'$Path\'");
8805 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008806 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008807 }
8808 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008809 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 my $TarCmd = get_CmdPath("tar");
8811 if(not $TarCmd) {
8812 exitStatus("Not_Found", "can't find \"tar\" command");
8813 }
8814 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008815 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008816 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008817 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 }
8819 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008820 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821 if(not @Contents) {
8822 exitStatus("Error", "can't extract \'$Path\'");
8823 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008824 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008825 }
8826 }
8827}
8828
8829sub createArchive($$)
8830{
8831 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008832 if(not $To) {
8833 $To = ".";
8834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008835 if(not $Path or not -e $Path
8836 or not -d $To) {
8837 return "";
8838 }
8839 my ($From, $Name) = separate_path($Path);
8840 if($OSgroup eq "windows")
8841 { # *.zip
8842 my $ZipCmd = get_CmdPath("zip");
8843 if(not $ZipCmd) {
8844 exitStatus("Not_Found", "can't find \"zip\"");
8845 }
8846 my $Pkg = $To."/".$Name.".zip";
8847 unlink($Pkg);
8848 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008849 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 if($?)
8851 { # cannot allocate memory (or other problems with "zip")
8852 unlink($Path);
8853 exitStatus("Error", "can't pack the ABI dump: ".$!);
8854 }
8855 chdir($ORIG_DIR);
8856 unlink($Path);
8857 return $Pkg;
8858 }
8859 else
8860 { # *.tar.gz
8861 my $TarCmd = get_CmdPath("tar");
8862 if(not $TarCmd) {
8863 exitStatus("Not_Found", "can't find \"tar\"");
8864 }
8865 my $GzipCmd = get_CmdPath("gzip");
8866 if(not $GzipCmd) {
8867 exitStatus("Not_Found", "can't find \"gzip\"");
8868 }
8869 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8870 unlink($Pkg);
8871 chdir($From);
8872 system($TarCmd, "-czf", $Pkg, $Name);
8873 if($?)
8874 { # cannot allocate memory (or other problems with "tar")
8875 unlink($Path);
8876 exitStatus("Error", "can't pack the ABI dump: ".$!);
8877 }
8878 chdir($ORIG_DIR);
8879 unlink($Path);
8880 return $To."/".$Name.".tar.gz";
8881 }
8882}
8883
8884sub is_header_file($)
8885{
8886 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8887 return $_[0];
8888 }
8889 return 0;
8890}
8891
8892sub is_not_header($)
8893{
8894 if($_[0]=~/\.\w+\Z/
8895 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8896 return 1;
8897 }
8898 return 0;
8899}
8900
8901sub is_header($$$)
8902{
8903 my ($Header, $UserDefined, $LibVersion) = @_;
8904 return 0 if(-d $Header);
8905 if(-f $Header) {
8906 $Header = get_abs_path($Header);
8907 }
8908 else
8909 {
8910 if(is_abs($Header))
8911 { # incorrect absolute path
8912 return 0;
8913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008914 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 $Header = $HPath;
8916 }
8917 else
8918 { # can't find header
8919 return 0;
8920 }
8921 }
8922 if($Header=~/\.\w+\Z/)
8923 { # have an extension
8924 return is_header_file($Header);
8925 }
8926 else
8927 {
8928 if($UserDefined==2)
8929 { # specified on the command line
8930 if(cmd_file($Header)!~/HTML|XML/i) {
8931 return $Header;
8932 }
8933 }
8934 elsif($UserDefined)
8935 { # specified in the XML-descriptor
8936 # header file without an extension
8937 return $Header;
8938 }
8939 else
8940 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008941 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008942 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008943 { # !~/HTML|XML|shared|dynamic/i
8944 return $Header;
8945 }
8946 }
8947 }
8948 return 0;
8949}
8950
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008951sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008952{
8953 my $LibVersion = $_[0];
8954 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8955 {
8956 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008957 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008958
8959 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8960 detect_recursive_includes($RegHeader, $LibVersion);
8961 }
8962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008963 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8964 {
8965 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008966
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008967 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008968 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8969 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008970 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008971 }
8972 }
8973 }
8974}
8975
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008976sub familiarDirs($$)
8977{
8978 my ($D1, $D2) = @_;
8979 if($D1 eq $D2) {
8980 return 1;
8981 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008982
8983 my $U1 = index($D1, "/usr/");
8984 my $U2 = index($D2, "/usr/");
8985
8986 if($U1==0 and $U2!=0) {
8987 return 0;
8988 }
8989
8990 if($U2==0 and $U1!=0) {
8991 return 0;
8992 }
8993
8994 if(index($D2, $D1."/")==0) {
8995 return 1;
8996 }
8997
8998 # /usr/include/DIR
8999 # /home/user/DIR
9000
9001 my $DL = get_depth($D1);
9002
9003 my @Dirs1 = ($D1);
9004 while($DL - get_depth($D1)<=2
9005 and get_depth($D1)>=4
9006 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9007 push(@Dirs1, $D1);
9008 }
9009
9010 my @Dirs2 = ($D2);
9011 while(get_depth($D2)>=4
9012 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9013 push(@Dirs2, $D2);
9014 }
9015
9016 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009017 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009018 foreach my $P2 (@Dirs2)
9019 {
9020
9021 if($P1 eq $P2) {
9022 return 1;
9023 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009024 }
9025 }
9026 return 0;
9027}
9028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009029sub readHeaders($)
9030{
9031 $Version = $_[0];
9032 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9033 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009034 if($Debug)
9035 { # debug mode
9036 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009037 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009038 }
9039 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009040}
9041
9042sub prepareTypes($)
9043{
9044 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009045 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009046 { # support for old ABI dumps
9047 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009048 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009049 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009050 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9051 if($TName=~/\A(\w+)::(\w+)/) {
9052 my ($P1, $P2) = ($1, $2);
9053 if($P1 eq $P2) {
9054 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009056 else {
9057 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009060 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009061 }
9062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009063 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009064 { # support for old ABI dumps
9065 # V < 2.5: array size == "number of elements"
9066 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009067 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009068 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009069 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009070 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009072 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009074 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009075 $Size *= $Base{"Size"};
9076 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009077 }
9078 else
9079 { # array[] is a pointer
9080 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009081 }
9082 }
9083 }
9084 }
9085 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009086 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009087 { # support for old ABI dumps
9088 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009089 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009090 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009091 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009092 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009093 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 my %Type = get_Type($TypeId, $LibVersion);
9095 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9096 my %Type2 = get_Type($TypeId_2, $V2);
9097 if($Type{"Size"} ne $Type2{"Size"}) {
9098 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009099 }
9100 }
9101 }
9102 }
9103}
9104
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009105sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009106{
9107 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009108
9109 if(not keys(%{$SymbolInfo{$LibVersion}}))
9110 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009111 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009112 {
9113 if($CheckHeadersOnly) {
9114 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9115 }
9116 else {
9117 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9118 }
9119 }
9120 }
9121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009122 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009123 if(not checkDump(1, "2.10")
9124 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009125 { # different formats
9126 $Remangle = 1;
9127 }
9128 if($CheckHeadersOnly)
9129 { # different languages
9130 if($UserLang)
9131 { # --lang=LANG for both versions
9132 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9133 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9134 {
9135 if($UserLang eq "C++")
9136 { # remangle symbols
9137 $Remangle = 1;
9138 }
9139 elsif($UserLang eq "C")
9140 { # remove mangling
9141 $Remangle = -1;
9142 }
9143 }
9144 }
9145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009146
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009147 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009149 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009150 { # support for old ABI dumps
9151 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9152 {
9153 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9154 {
9155 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9156 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009157 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009158 if(defined $DVal and $DVal ne "")
9159 {
9160 if($TName eq "char") {
9161 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9162 }
9163 elsif($TName eq "bool") {
9164 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9165 }
9166 }
9167 }
9168 }
9169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009170 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009172 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9173 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009174 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9176 # + support for old ABI dumps
9177 next;
9178 }
9179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009180 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009181 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009182 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009183 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009184
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009185 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009186 if(not checkDump(1, "2.12")
9187 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009188 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009189 if($ShortName eq "operator>>")
9190 {
9191 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9192 { # corrected mangling of operator>>
9193 $SRemangle = 1;
9194 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009195 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009196 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9197 {
9198 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9199 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9200 { # corrected mangling of const global data
9201 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9202 # and incorrectly mangled by old ACC versions
9203 $SRemangle = 1;
9204 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009205 }
9206 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009207 if(not $CheckHeadersOnly)
9208 { # support for old ABI dumps
9209 if(not checkDump(1, "2.17")
9210 or not checkDump(2, "2.17"))
9211 {
9212 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9213 {
9214 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9215 {
9216 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9217 {
9218 $MnglName = $ShortName;
9219 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9220 }
9221 }
9222 }
9223 }
9224 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009225 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009226 { # support for old ABI dumps: some symbols are not mangled in old dumps
9227 # mangle both sets of symbols (old and new)
9228 # NOTE: remangling all symbols by the same mangler
9229 if($MnglName=~/\A_ZN(V|)K/)
9230 { # mangling may be incorrect on old ABI dumps
9231 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009232 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009233 }
9234 if($MnglName=~/\A_ZN(K|)V/)
9235 { # mangling may be incorrect on old ABI dumps
9236 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009237 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009238 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009239 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9240 or (not $ClassID and $CheckHeadersOnly)
9241 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9242 { # support for old ABI dumps, GCC >= 4.0
9243 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009244 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009245 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009246 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 $MangledNames{$LibVersion}{$MnglName} = 1;
9248 }
9249 }
9250 }
9251 elsif($Remangle==-1)
9252 { # remove mangling
9253 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009254 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009256 if(not $MnglName) {
9257 next;
9258 }
9259 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9260 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009261 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009263 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009264 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009265 { # support for old dumps
9266 # add "Volatile" attribute
9267 if($MnglName=~/_Z(K|)V/) {
9268 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9269 }
9270 }
9271 # symbol and its symlink have same signatures
9272 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009273 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009274 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009275
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009276 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9277 {
9278 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9279 if($SymVer{$LibVersion}{$Alias}) {
9280 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9281 }
9282 }
9283
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009284 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009285 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009286 }
9287 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9288 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9289 }
9290 if($ExtendedCheck)
9291 { # --ext option
9292 addExtension($LibVersion);
9293 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009294
9295 # clean memory
9296 delete($SymbolInfo{$LibVersion});
9297
9298 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009299 { # detect allocable classes with public exported constructors
9300 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009301 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009302 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009304 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009305 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9306 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009307 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009308 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009310 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009311 $AllocableClass{$LibVersion}{$ClassName} = 1;
9312 }
9313 }
9314 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009315 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009317 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009319 if($CheckHeadersOnly)
9320 {
9321 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9322 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9323 { # all symbols except non-virtual inline
9324 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9325 }
9326 }
9327 else {
9328 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009329 }
9330 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009331 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009332 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 }
9334 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009335 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009336 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009337 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009338 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009339 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009340 if(defined $Base{"Type"}
9341 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009342 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009343 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009344 if($Name=~/<([^<>\s]+)>/)
9345 {
9346 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9347 $ReturnedClass{$LibVersion}{$Tid} = 1;
9348 }
9349 }
9350 else {
9351 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9352 }
9353 }
9354 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009355 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009356 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009357 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009358 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009360 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009362 if($Base{"Type"}=~/Struct|Class/)
9363 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009365 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9366 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009367 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 }
9370 }
9371 }
9372 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009373
9374 # mapping {short name => symbols}
9375 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009377 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009378 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009379 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009380 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009381 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009382 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009383 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9384 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009385 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009386 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 }
9388 }
9389 }
9390 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009391
9392 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009393 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009395 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009397 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9398 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009402 $ClassNames{$LibVersion}{$TName} = 1;
9403 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9406 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 }
9408 }
9409 }
9410 }
9411 }
9412}
9413
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009414sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009415{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009416 my ($Tid, $LibVersion) = @_;
9417 if(not $Tid) {
9418 return $Tid;
9419 }
9420
9421 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9422 {
9423 if($TName_Tid{$LibVersion}{$Name}) {
9424 return $TName_Tid{$LibVersion}{$Name};
9425 }
9426 }
9427
9428 return $Tid;
9429}
9430
9431sub register_SymbolUsage($$$)
9432{
9433 my ($InfoId, $UsedType, $LibVersion) = @_;
9434
9435 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9436 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9437 {
9438 register_TypeUsage($RTid, $UsedType, $LibVersion);
9439 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9440 }
9441 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9442 {
9443 register_TypeUsage($FCid, $UsedType, $LibVersion);
9444 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9445
9446 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9447 { # register "this" pointer
9448 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9449 }
9450 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9451 { # register "this" pointer (const method)
9452 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9453 }
9454 }
9455 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9456 {
9457 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9458 {
9459 register_TypeUsage($PTid, $UsedType, $LibVersion);
9460 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9461 }
9462 }
9463 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9464 {
9465 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9466 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9467 register_TypeUsage($TTid, $UsedType, $LibVersion);
9468 }
9469 }
9470}
9471
9472sub register_TypeUsage($$$)
9473{
9474 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009475 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009476 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009477 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009478 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009479 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009480 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009481 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009482
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009483 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009484 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009485 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009486 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009488 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9489 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9490 }
9491 }
9492
9493 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9494 {
9495 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009496 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009497 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009498 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9499 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009500 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9502 {
9503 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9504 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009505 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009506 }
9507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009508 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009509 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009510 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009511 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9512 {
9513 register_TypeUsage($MTid, $UsedType, $LibVersion);
9514 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009515 }
9516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009517 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009518 or $TInfo{"Type"} eq "MethodPtr"
9519 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009520 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009521 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009522 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009523 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009524 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009525 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009526 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9527 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009528 }
9529 }
9530 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009531 if($TInfo{"Type"} eq "FieldPtr")
9532 {
9533 if(my $RTid = $TInfo{"Return"}) {
9534 register_TypeUsage($RTid, $UsedType, $LibVersion);
9535 }
9536 if(my $CTid = $TInfo{"Class"}) {
9537 register_TypeUsage($CTid, $UsedType, $LibVersion);
9538 }
9539 }
9540 if($TInfo{"Type"} eq "MethodPtr")
9541 {
9542 if(my $CTid = $TInfo{"Class"}) {
9543 register_TypeUsage($CTid, $UsedType, $LibVersion);
9544 }
9545 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009547 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009548 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009549 $UsedType->{$TypeId} = 1;
9550 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9551 {
9552 register_TypeUsage($BTid, $UsedType, $LibVersion);
9553 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9554 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009555 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009556 else
9557 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9558 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009559 }
9560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009561}
9562
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009563sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009564{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009565 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9566
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009567 if($Level eq "Dump")
9568 {
9569 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9570 { # TODO: check if this symbol is from
9571 # base classes of other target symbols
9572 return 1;
9573 }
9574 }
9575
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009576 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9577 { # stdc++ interfaces
9578 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009579 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009580
9581 my $Target = 0;
9582 if(my $Header = $SInfo->{"Header"}) {
9583 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9584 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009585 if($ExtendedCheck)
9586 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009587 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009588 $Target = 1;
9589 }
9590 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009591 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009592 {
9593 if($Target)
9594 {
9595 if($Level eq "Dump")
9596 { # dumped
9597 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009598 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009599 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009600 return 1;
9601 }
9602 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009603 else {
9604 return 1;
9605 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009606 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009607 elsif($Level eq "Source")
9608 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009609 return 1;
9610 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009611 elsif($Level eq "Binary")
9612 { # checked
9613 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9614 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9615 return 1;
9616 }
9617 }
9618 }
9619 }
9620 else
9621 { # library is available
9622 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9623 { # exported symbols
9624 return 1;
9625 }
9626 if($Level eq "Dump")
9627 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009628 if($BinaryOnly)
9629 {
9630 if($SInfo->{"Data"})
9631 {
9632 if($Target) {
9633 return 1;
9634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009635 }
9636 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009637 else
9638 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639 if($Target) {
9640 return 1;
9641 }
9642 }
9643 }
9644 elsif($Level eq "Source")
9645 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009646 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009647 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009648 { # skip LOCAL symbols
9649 if($Target) {
9650 return 1;
9651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652 }
9653 }
9654 elsif($Level eq "Binary")
9655 { # checked
9656 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9657 {
9658 if($Target) {
9659 return 1;
9660 }
9661 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009662 }
9663 }
9664 return 0;
9665}
9666
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009667sub cleanDump($)
9668{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009669 my $LibVersion = $_[0];
9670 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9671 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009672 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9673 {
9674 delete($SymbolInfo{$LibVersion}{$InfoId});
9675 next;
9676 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009677 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009678 if(not $MnglName)
9679 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009680 delete($SymbolInfo{$LibVersion}{$InfoId});
9681 next;
9682 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009683 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009684 if(not $ShortName)
9685 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009686 delete($SymbolInfo{$LibVersion}{$InfoId});
9687 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009688 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009689 if($MnglName eq $ShortName)
9690 { # remove duplicate data
9691 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009692 }
9693 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9694 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9695 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009696 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9697 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9698 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009699 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009700 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009701 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009702 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009703 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9704 {
9705 delete($TypeInfo{$LibVersion}{$Tid});
9706 next;
9707 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009708 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009709 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009710 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009711 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9712 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9713 }
9714 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009715 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9716 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009718 }
9719}
9720
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009721sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009722{
9723 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009724
9725 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9726 {
9727 if(defined $TypeInfo{$LibVersion}{$Dupl})
9728 {
9729 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9730 { # duplicate
9731 return 0;
9732 }
9733 }
9734 }
9735
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009736 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9737
9738 if(isBuiltIn($THeader)) {
9739 return 0;
9740 }
9741
9742 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9743 return 0;
9744 }
9745
9746 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9747 return 0;
9748 }
9749
9750 if(selfTypedef($Tid, $LibVersion)) {
9751 return 0;
9752 }
9753
9754 if(not isTargetType($Tid, $LibVersion)) {
9755 return 0;
9756 }
9757
9758 return 0;
9759}
9760
9761sub isTargetType($$)
9762{
9763 my ($Tid, $LibVersion) = @_;
9764
9765 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9766 { # derived
9767 return 1;
9768 }
9769
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009770 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9771 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009772 if(not is_target_header($THeader, $LibVersion))
9773 { # from target headers
9774 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009775 }
9776 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009777
9778 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009779}
9780
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009781sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009782{ # remove unused data types from the ABI dump
9783 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009784
9785 my %UsedType = ();
9786
9787 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009788 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009789 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009790 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009791 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009792 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009793 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009794 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009795 next;
9796 }
9797
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009798 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009799 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009800 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009801 {
9802 my %Tree = ();
9803 register_TypeUsage($Tid, \%Tree, $LibVersion);
9804
9805 my $Tmpl = 0;
9806 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9807 {
9808 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9809 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9810 {
9811 $Tmpl = 1;
9812 last;
9813 }
9814 }
9815 if(not $Tmpl)
9816 {
9817 foreach (keys(%Tree)) {
9818 $UsedType{$_} = 1;
9819 }
9820 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009821 }
9822 }
9823 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009824
9825 my %Delete = ();
9826
9827 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009828 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009829 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009830 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009831 next;
9832 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009833
9834 if($Kind eq "Extra")
9835 {
9836 my %Tree = ();
9837 register_TypeUsage($Tid, \%Tree, $LibVersion);
9838
9839 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9840 {
9841 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9842 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9843 {
9844 $Delete{$Tid} = 1;
9845 last;
9846 }
9847 }
9848 }
9849 else
9850 {
9851 # remove type
9852 delete($TypeInfo{$LibVersion}{$Tid});
9853 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009854 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009855
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009856 if($Kind eq "Extra")
9857 { # remove duplicates
9858 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9859 {
9860 if($UsedType{$Tid})
9861 { # All & Extended
9862 next;
9863 }
9864
9865 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9866
9867 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9868 delete($TypeInfo{$LibVersion}{$Tid});
9869 }
9870 }
9871 }
9872
9873 foreach my $Tid (keys(%Delete))
9874 {
9875 delete($TypeInfo{$LibVersion}{$Tid});
9876 }
9877}
9878
9879sub check_Completeness($$)
9880{
9881 my ($Info, $LibVersion) = @_;
9882
9883 # data types
9884 if(defined $Info->{"Memb"})
9885 {
9886 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9887 {
9888 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9889 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9890 }
9891 }
9892 }
9893 if(defined $Info->{"Base"})
9894 {
9895 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9896 check_TypeInfo($Bid, $LibVersion);
9897 }
9898 }
9899 if(defined $Info->{"BaseType"}) {
9900 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9901 }
9902 if(defined $Info->{"TParam"})
9903 {
9904 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9905 {
9906 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9907 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9908 next;
9909 }
9910 if($TName eq "_BoolType") {
9911 next;
9912 }
9913 if($TName=~/\Asizeof\(/) {
9914 next;
9915 }
9916 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9917 check_TypeInfo($Tid, $LibVersion);
9918 }
9919 else
9920 {
9921 if(defined $Debug) {
9922 printMsg("WARNING", "missed type $TName");
9923 }
9924 }
9925 }
9926 }
9927
9928 # symbols
9929 if(defined $Info->{"Param"})
9930 {
9931 foreach my $Pos (keys(%{$Info->{"Param"}}))
9932 {
9933 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9934 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9935 }
9936 }
9937 }
9938 if(defined $Info->{"Return"}) {
9939 check_TypeInfo($Info->{"Return"}, $LibVersion);
9940 }
9941 if(defined $Info->{"Class"}) {
9942 check_TypeInfo($Info->{"Class"}, $LibVersion);
9943 }
9944}
9945
9946sub check_TypeInfo($$)
9947{
9948 my ($Tid, $LibVersion) = @_;
9949
9950 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9951 return;
9952 }
9953 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9954
9955 if(defined $TypeInfo{$LibVersion}{$Tid})
9956 {
9957 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9958 printMsg("ERROR", "missed type name ($Tid)");
9959 }
9960 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9961 }
9962 else {
9963 printMsg("ERROR", "missed type id $Tid");
9964 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009965}
9966
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009967sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009968{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009969 my ($TypeId, $LibVersion) = @_;
9970 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009971 if($Type{"Type"} eq "Typedef")
9972 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009973 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009974 if($Base{"Type"}=~/Class|Struct/)
9975 {
9976 if($Type{"Name"} eq $Base{"Name"}) {
9977 return 1;
9978 }
9979 elsif($Type{"Name"}=~/::(\w+)\Z/)
9980 {
9981 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9982 { # QPointer<QWidget>::QPointer
9983 return 1;
9984 }
9985 }
9986 }
9987 }
9988 return 0;
9989}
9990
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009991sub addExtension($)
9992{
9993 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009994 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009995 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009996 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009997 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009998 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9999 $TName=~s/\A(struct|union|class|enum) //;
10000 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010001
10002 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10003 "Header" => "extended.h",
10004 "ShortName" => $Symbol,
10005 "MnglName" => $Symbol,
10006 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10007 );
10008
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010009 $ExtendedSymbols{$Symbol} = 1;
10010 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10011 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010012 }
10013 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010014 $ExtendedSymbols{"external_func_0"} = 1;
10015 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10016 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010017}
10018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010019sub findMethod($$$)
10020{
10021 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010022 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010023 {
10024 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10025 return $VirtMethodInClass;
10026 }
10027 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10028 return $VirtMethodInBaseClasses;
10029 }
10030 }
10031 return "";
10032}
10033
10034sub findMethod_Class($$$)
10035{
10036 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010037 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010038 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10039 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10040 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10041 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10042 { # search for interface with the same parameters suffix (overridden)
10043 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10044 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010045 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10046 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010047 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10048 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010049 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10050 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10051 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10052 return $Candidate;
10053 }
10054 }
10055 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010056 else
10057 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010058 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10059 return $Candidate;
10060 }
10061 }
10062 }
10063 }
10064 return "";
10065}
10066
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010067sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010068{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010069 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010070 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010072 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10073 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010074 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010075 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010076 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010077 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10078 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010079 { # pure virtual D2-destructors are marked as "virt" in the dump
10080 # virtual D2-destructors are NOT marked as "virt" in the dump
10081 # both destructors are not presented in the v-table
10082 next;
10083 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010084 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010085 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010087 }
10088}
10089
10090sub registerOverriding($)
10091{
10092 my $LibVersion = $_[0];
10093 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010094 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010095 foreach my $ClassName (@Classes)
10096 {
10097 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10098 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010099 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10100 { # pure virtuals
10101 next;
10102 }
10103 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10104 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010105 {
10106 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10107 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10108 { # both overridden virtual methods
10109 # and implemented pure virtual methods
10110 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10111 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10112 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010114 }
10115 }
10116 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10117 delete($VirtualTable{$LibVersion}{$ClassName});
10118 }
10119 }
10120}
10121
10122sub setVirtFuncPositions($)
10123{
10124 my $LibVersion = $_[0];
10125 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10126 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010127 my ($Num, $Rel) = (1, 0);
10128
10129 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010130 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010131 if($UsedDump{$LibVersion}{"DWARF"}) {
10132 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10133 }
10134 else {
10135 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10136 }
10137 foreach my $VirtFunc (@Funcs)
10138 {
10139 if($UsedDump{$LibVersion}{"DWARF"}) {
10140 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10141 }
10142 else {
10143 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10144 }
10145
10146 # set relative positions
10147 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10148 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10149 { # relative position excluding added and removed virtual functions
10150 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10151 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10152 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 }
10157 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010158 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 {
10160 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010161 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010162 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010163 }
10164 }
10165}
10166
10167sub get_sub_classes($$$)
10168{
10169 my ($ClassId, $LibVersion, $Recursive) = @_;
10170 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10171 my @Subs = ();
10172 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10173 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174 if($Recursive)
10175 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10177 push(@Subs, $SubSubId);
10178 }
10179 }
10180 push(@Subs, $SubId);
10181 }
10182 return @Subs;
10183}
10184
10185sub get_base_classes($$$)
10186{
10187 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010188 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010189 return () if(not defined $ClassType{"Base"});
10190 my @Bases = ();
10191 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10192 keys(%{$ClassType{"Base"}}))
10193 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010194 if($Recursive)
10195 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010196 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10197 push(@Bases, $SubBaseId);
10198 }
10199 }
10200 push(@Bases, $BaseId);
10201 }
10202 return @Bases;
10203}
10204
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010205sub getVTable_Model($$)
10206{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 my ($ClassId, $LibVersion) = @_;
10208 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10209 my @Elements = ();
10210 foreach my $BaseId (@Bases, $ClassId)
10211 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010212 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010213 {
10214 if(defined $VirtualTable{$LibVersion}{$BName})
10215 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010216 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10217 if($UsedDump{$LibVersion}{"DWARF"}) {
10218 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10219 }
10220 else {
10221 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10222 }
10223 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010224 push(@Elements, $VFunc);
10225 }
10226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010227 }
10228 }
10229 return @Elements;
10230}
10231
10232sub getVShift($$)
10233{
10234 my ($ClassId, $LibVersion) = @_;
10235 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10236 my $VShift = 0;
10237 foreach my $BaseId (@Bases)
10238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010239 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010240 {
10241 if(defined $VirtualTable{$LibVersion}{$BName}) {
10242 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010244 }
10245 }
10246 return $VShift;
10247}
10248
10249sub getShift($$)
10250{
10251 my ($ClassId, $LibVersion) = @_;
10252 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10253 my $Shift = 0;
10254 foreach my $BaseId (@Bases)
10255 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010256 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010257 {
10258 if($Size!=1)
10259 { # not empty base class
10260 $Shift+=$Size;
10261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010262 }
10263 }
10264 return $Shift;
10265}
10266
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010267sub getVTable_Size($$)
10268{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010269 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010270 my $Size = 0;
10271 # three approaches
10272 if(not $Size)
10273 { # real size
10274 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10275 $Size = keys(%VTable);
10276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010277 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010278 if(not $Size)
10279 { # shared library symbol size
10280 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10281 $Size /= $WORD_SIZE{$LibVersion};
10282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010283 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010284 if(not $Size)
10285 { # model size
10286 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10287 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10288 }
10289 }
10290 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010291}
10292
10293sub isCopyingClass($$)
10294{
10295 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010296 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010297}
10298
10299sub isLeafClass($$)
10300{
10301 my ($ClassId, $LibVersion) = @_;
10302 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10303}
10304
10305sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010306{ # check structured type for public fields
10307 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010308}
10309
10310sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010311{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312 my ($TypePtr, $Skip, $Start, $End) = @_;
10313 return 0 if(not $TypePtr);
10314 if($End==-1) {
10315 $End = keys(%{$TypePtr->{"Memb"}})-1;
10316 }
10317 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10318 {
10319 if($Skip and $Skip->{$MemPos})
10320 { # skip removed/added fields
10321 next;
10322 }
10323 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10324 {
10325 if(isPublic($TypePtr, $MemPos)) {
10326 return ($MemPos+1);
10327 }
10328 }
10329 }
10330 return 0;
10331}
10332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333sub isReserved($)
10334{ # reserved fields == private
10335 my $MName = $_[0];
10336 if($MName=~/reserved|padding|f_spare/i) {
10337 return 1;
10338 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010339 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010340 return 1;
10341 }
10342 if($MName=~/(pad\d+)/i) {
10343 return 1;
10344 }
10345 return 0;
10346}
10347
10348sub isPublic($$)
10349{
10350 my ($TypePtr, $FieldPos) = @_;
10351 return 0 if(not $TypePtr);
10352 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10353 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10354 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10355 { # by name in C language
10356 # FIXME: add other methods to detect private members
10357 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10358 if($MName=~/priv|abidata|parent_object/i)
10359 { # C-styled private data
10360 return 0;
10361 }
10362 if(lc($MName) eq "abi")
10363 { # ABI information/reserved field
10364 return 0;
10365 }
10366 if(isReserved($MName))
10367 { # reserved fields
10368 return 0;
10369 }
10370 return 1;
10371 }
10372 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10373 { # by access in C++ language
10374 return 1;
10375 }
10376 return 0;
10377}
10378
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010379sub getVTable_Real($$)
10380{
10381 my ($ClassName, $LibVersion) = @_;
10382 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010384 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010385 if(defined $Type{"VTable"}) {
10386 return %{$Type{"VTable"}};
10387 }
10388 }
10389 return ();
10390}
10391
10392sub cmpVTables($)
10393{
10394 my $ClassName = $_[0];
10395 my $Res = cmpVTables_Real($ClassName, 1);
10396 if($Res==-1) {
10397 $Res = cmpVTables_Model($ClassName);
10398 }
10399 return $Res;
10400}
10401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010402sub cmpVTables_Model($)
10403{
10404 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010405 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010406 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010407 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010408 return 1;
10409 }
10410 }
10411 return 0;
10412}
10413
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010415{
10416 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010417 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10418 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010419 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420 my %VTable_Old = getVTable_Real($ClassName, 1);
10421 my %VTable_New = getVTable_Real($ClassName, 2);
10422 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010423 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010424 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010425 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010426 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010427 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10428 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010429 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010431 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 my $Entry1 = $VTable_Old{$Offset};
10434 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010435 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010436 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010438 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 $Entry1 = simpleVEntry($Entry1);
10441 $Entry2 = simpleVEntry($Entry2);
10442 if($Entry1 ne $Entry2)
10443 { # register as changed
10444 if($Entry1=~/::([^:]+)\Z/)
10445 {
10446 my $M1 = $1;
10447 if($Entry2=~/::([^:]+)\Z/)
10448 {
10449 my $M2 = $1;
10450 if($M1 eq $M2)
10451 { # overridden
10452 next;
10453 }
10454 }
10455 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010456 if(differentDumps("G"))
10457 {
10458 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10459 {
10460 # GCC 4.6.1: -0x00000000000000010
10461 # GCC 4.7.0: -16
10462 next;
10463 }
10464 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010465 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010466 }
10467 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010468 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010469}
10470
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010471sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010473 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010474 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10475 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010476 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477 { # already registered
10478 next;
10479 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010480 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010481 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010482 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010483 foreach my $Symbol (@Affected)
10484 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010485 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487 "Target"=>$ClassName);
10488 }
10489 }
10490 }
10491}
10492
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010493sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010494{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010495 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010498 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010499 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010500 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010501 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010503 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 if($TName_Tid{1}{$ClassName}
10505 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010506 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010507 if(defined $CompleteSignature{1}{$Symbol}
10508 and $CompleteSignature{1}{$Symbol}{"Virt"})
10509 { # override some method in v.1
10510 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010511 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010512 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513 }
10514 }
10515 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010516 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010519 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 if($TName_Tid{2}{$ClassName}
10521 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010522 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 if(defined $CompleteSignature{2}{$Symbol}
10524 and $CompleteSignature{2}{$Symbol}{"Virt"})
10525 { # override some method in v.2
10526 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010527 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 }
10530 }
10531 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010532 if($Level eq "Binary")
10533 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010534 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010535 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10536 { # check replacements, including pure virtual methods
10537 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10538 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010539 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010540 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10541 if($AddedPos==$RemovedPos)
10542 {
10543 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10544 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10545 last; # other methods will be reported as "added" or "removed"
10546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010548 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10549 {
10550 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10551 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010552 next;
10553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010554 my $ProblemType = "Virtual_Replacement";
10555 my @Affected = ($RemovedVFunc);
10556 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10557 { # pure methods
10558 if(not isUsedClass($ClassId, 1, $Level))
10559 { # not a parameter of some exported method
10560 next;
10561 }
10562 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010563
10564 # affected all methods (both virtual and non-virtual ones)
10565 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10566 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010568 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010569 foreach my $AffectedInt (@Affected)
10570 {
10571 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10572 { # affected exported methods only
10573 next;
10574 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010575 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10576 next;
10577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010578 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10579 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010580 "Target"=>get_Signature($AddedVFunc, 2),
10581 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 }
10584 }
10585 }
10586 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010587 if(not checkDump(1, "2.0")
10588 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010589 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010590 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 return;
10592 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 next if(not $ClassId_Old);
10597 if(not isCreatable($ClassId_Old, 1))
10598 { # skip classes without public constructors (including auto-generated)
10599 # example: class has only a private exported or private inline constructor
10600 next;
10601 }
10602 if($ClassName=~/>/)
10603 { # skip affected template instances
10604 next;
10605 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010606 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010607 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010608 if(not $ClassId_New) {
10609 next;
10610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010611 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010612 if($Class_New{"Type"}!~/Class|Struct/)
10613 { # became typedef
10614 if($Level eq "Binary") {
10615 next;
10616 }
10617 if($Level eq "Source")
10618 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010619 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010620 if($Class_New{"Type"}!~/Class|Struct/) {
10621 next;
10622 }
10623 $ClassId_New = $Class_New{"Tid"};
10624 }
10625 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010626
10627 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10628 { # incomplete info in the ABI dump
10629 next;
10630 }
10631
10632
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10634 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 +040010635
10636 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10637 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010640 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10641 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010642 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10643 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010644 my $Shift_Old = getShift($ClassId_Old, 1);
10645 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010646 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 my ($Added, $Removed) = (0, 0);
10648 my @StableBases_Old = ();
10649 foreach my $BaseId (@Bases_Old)
10650 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010651 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010652 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 push(@StableBases_Old, $BaseId);
10654 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010655 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010656 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 { # removed base
10658 # excluding namespace::SomeClass to SomeClass renaming
10659 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010660 if($Level eq "Binary")
10661 { # Binary-level
10662 if($Shift_Old ne $Shift_New)
10663 { # affected fields
10664 if(havePubFields(\%Class_Old)) {
10665 $ProblemKind .= "_And_Shift";
10666 }
10667 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10668 $ProblemKind .= "_And_Size";
10669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010670 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010671 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10672 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010673 { # affected v-table
10674 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010675 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 }
10677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010678 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10680 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010681 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10682 {
10683 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10684 if($ProblemKind=~/VTable/) {
10685 $VTableChanged_M{$SubName}=1;
10686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 }
10688 }
10689 foreach my $Interface (@Affected)
10690 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010691 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10692 next;
10693 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010694 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010696 "Target"=>$BaseName,
10697 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10698 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10699 "Shift"=>abs($Shift_New-$Shift_Old) );
10700 }
10701 $Removed+=1;
10702 }
10703 }
10704 my @StableBases_New = ();
10705 foreach my $BaseId (@Bases_New)
10706 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010707 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010708 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010709 push(@StableBases_New, $BaseId);
10710 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010711 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010712 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010713 { # added base
10714 # excluding namespace::SomeClass to SomeClass renaming
10715 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010716 if($Level eq "Binary")
10717 { # Binary-level
10718 if($Shift_Old ne $Shift_New)
10719 { # affected fields
10720 if(havePubFields(\%Class_Old)) {
10721 $ProblemKind .= "_And_Shift";
10722 }
10723 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10724 $ProblemKind .= "_And_Size";
10725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010726 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010727 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10728 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010729 { # affected v-table
10730 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010731 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010732 }
10733 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010734 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10736 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010737 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10738 {
10739 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10740 if($ProblemKind=~/VTable/) {
10741 $VTableChanged_M{$SubName}=1;
10742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010743 }
10744 }
10745 foreach my $Interface (@Affected)
10746 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010747 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10748 next;
10749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010750 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010752 "Target"=>$BaseName,
10753 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10754 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10755 "Shift"=>abs($Shift_New-$Shift_Old) );
10756 }
10757 $Added+=1;
10758 }
10759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010760 if($Level eq "Binary")
10761 { # Binary-level
10762 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010763 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10764 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010765 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010767 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010768 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010770 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10771 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010772 if($NewPos!=$OldPos)
10773 { # changed position of the base class
10774 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010775 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010776 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10777 next;
10778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010779 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10780 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010781 "Target"=>$BaseName,
10782 "Old_Value"=>$OldPos-1,
10783 "New_Value"=>$NewPos-1 );
10784 }
10785 }
10786 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10787 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10788 { # became non-virtual base
10789 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10790 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010791 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10792 next;
10793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010794 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10795 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010796 "Target"=>$BaseName );
10797 }
10798 }
10799 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10800 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10801 { # became virtual base
10802 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10803 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010804 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10805 next;
10806 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010807 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10808 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010809 "Target"=>$BaseName );
10810 }
10811 }
10812 }
10813 }
10814 # detect size changes in base classes
10815 if($Shift_Old!=$Shift_New)
10816 { # size of allocable class
10817 foreach my $BaseId (@StableBases_Old)
10818 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010819 my %BaseType = get_Type($BaseId, 1);
10820 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010821 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010822 if($Size_Old ne $Size_New
10823 and $Size_Old and $Size_New)
10824 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010825 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010826 if(isCopyingClass($BaseId, 1)) {
10827 $ProblemType = "Size_Of_Copying_Class";
10828 }
10829 elsif($AllocableClass{1}{$BaseType{"Name"}})
10830 {
10831 if($Size_New>$Size_Old)
10832 { # increased size
10833 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010835 else
10836 { # decreased size
10837 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10838 if(not havePubFields(\%Class_Old))
10839 { # affected class has no public members
10840 next;
10841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010843 }
10844 next if(not $ProblemType);
10845 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10846 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010847 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10848 next;
10849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10851 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010852 "Target"=>$BaseType{"Name"},
10853 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10854 "New_Size"=>$Size_New*$BYTE_SIZE );
10855 }
10856 }
10857 }
10858 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010859 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010860 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010862 { # compare virtual tables size in base classes
10863 my $VShift_Old = getVShift($ClassId_Old, 1);
10864 my $VShift_New = getVShift($ClassId_New, 2);
10865 if($VShift_Old ne $VShift_New)
10866 { # changes in the base class or changes in the list of base classes
10867 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10868 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10869 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010870 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010871 foreach my $BaseId (@AllBases_Old)
10872 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010873 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010874 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 { # lost base
10876 next;
10877 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010878 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10879 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010880 if($VSize_Old!=$VSize_New)
10881 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010882 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010883 { # TODO: affected non-virtual methods?
10884 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010885 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10886 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010887 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010888 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010889 { # skip interfaces that have not changed the absolute virtual position
10890 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010891 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010892 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10893 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010894 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010895 $VTableChanged_M{$BaseType{"Name"}} = 1;
10896 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10898 { # the reason of the layout change: added virtual functions
10899 next if($VirtualReplacement{$VirtFunc});
10900 my $ProblemType = "Added_Virtual_Method";
10901 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10902 $ProblemType = "Added_Pure_Virtual_Method";
10903 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010904 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010905 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010906 "Target"=>get_Signature($VirtFunc, 2) );
10907 }
10908 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10909 { # the reason of the layout change: removed virtual functions
10910 next if($VirtualReplacement{$VirtFunc});
10911 my $ProblemType = "Removed_Virtual_Method";
10912 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10913 $ProblemType = "Removed_Pure_Virtual_Method";
10914 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010915 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010916 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010917 "Target"=>get_Signature($VirtFunc, 1) );
10918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010919 }
10920 }
10921 }
10922 }
10923 }
10924 }
10925 }
10926}
10927
10928sub isCreatable($$)
10929{
10930 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010931 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 or isCopyingClass($ClassId, $LibVersion)) {
10933 return 1;
10934 }
10935 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10936 { # Fix for incomplete data: if this class has
10937 # a base class then it should also has a constructor
10938 return 1;
10939 }
10940 if($ReturnedClass{$LibVersion}{$ClassId})
10941 { # returned by some method of this class
10942 # or any other class
10943 return 1;
10944 }
10945 return 0;
10946}
10947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010948sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010949{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010950 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010951 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10952 { # parameter of some exported method
10953 return 1;
10954 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010955 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10956 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010957 { # method from target class
10958 return 1;
10959 }
10960 return 0;
10961}
10962
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010963sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010964{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010965 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010966 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010967 # - virtual
10968 # - pure-virtual
10969 # - non-virtual
10970 if($CompleteSignature{1}{$Interface}{"Data"})
10971 { # global data is not affected
10972 return;
10973 }
10974 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010975 if(not $Class_Id) {
10976 return;
10977 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010978 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010979 if(cmpVTables_Real($CName, 1)==0)
10980 { # no changes
10981 return;
10982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 $CheckedTypes{$Level}{$CName} = 1;
10984 if($Level eq "Binary")
10985 { # Binary-level
10986 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10987 and not isUsedClass($Class_Id, 1, $Level))
10988 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010989 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010990 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010991 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010992 }
10993 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10994 {
10995 if(defined $VirtualTable{2}{$CName}{$Func}
10996 and defined $CompleteSignature{2}{$Func})
10997 {
10998 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10999 and $CompleteSignature{2}{$Func}{"PureVirt"})
11000 { # became pure virtual
11001 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11002 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011003 "Target"=>get_Signature_M($Func, 1) );
11004 $VTableChanged_M{$CName} = 1;
11005 }
11006 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11007 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11008 { # became non-pure virtual
11009 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11010 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011011 "Target"=>get_Signature_M($Func, 1) );
11012 $VTableChanged_M{$CName} = 1;
11013 }
11014 }
11015 }
11016 if($Level eq "Binary")
11017 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011018 # check virtual table structure
11019 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11020 {
11021 next if($Interface eq $AddedVFunc);
11022 next if($VirtualReplacement{$AddedVFunc});
11023 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11024 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11025 { # pure virtual methods affect all others (virtual and non-virtual)
11026 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011027 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011028 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011029 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011030 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011031 elsif(not defined $VirtualTable{1}{$CName}
11032 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011034 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011035 { # became polymorphous class, added v-table pointer
11036 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011037 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011039 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040 }
11041 else
11042 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011043 my $VSize_Old = getVTable_Size($CName, 1);
11044 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011045 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011046 if(isCopyingClass($Class_Id, 1))
11047 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11048 my $ProblemType = "Added_Virtual_Method";
11049 if(isLeafClass($Class_Id, 1)) {
11050 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11051 }
11052 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11053 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011055 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011056 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 else
11058 {
11059 my $ProblemType = "Added_Virtual_Method";
11060 if(isLeafClass($Class_Id, 1)) {
11061 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11062 }
11063 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11064 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011066 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011068 }
11069 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11071 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011073 if(defined $VirtualTable{1}{$CName}
11074 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011075 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011076 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11077 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011078
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011079 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011080 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011081 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11082 foreach my $ASymbol (@Affected)
11083 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011084 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11085 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011086 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011087 next;
11088 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011089 }
11090 $CheckedSymbols{$Level}{$ASymbol} = 1;
11091 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11092 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011093 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011094 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011097 }
11098 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 else {
11100 # safe
11101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011102 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011103 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11104 {
11105 next if($VirtualReplacement{$RemovedVFunc});
11106 if($RemovedVFunc eq $Interface
11107 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11108 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011109 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011110 next;
11111 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011112 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011113 { # became non-polymorphous class, removed v-table pointer
11114 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11115 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011116 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011117 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011118 }
11119 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11120 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11121 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011122 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011123 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011124 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11125 next;
11126 }
11127 my $VPos_New = -1;
11128 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011130 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11131 }
11132 else
11133 {
11134 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 next;
11136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011137 }
11138 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11139 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11140 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11141 {
11142 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11143 foreach my $ASymbol (@Affected)
11144 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011145 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11146 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011147 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011148 next;
11149 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011150 }
11151 my $ProblemType = "Removed_Virtual_Method";
11152 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11153 $ProblemType = "Removed_Pure_Virtual_Method";
11154 }
11155 $CheckedSymbols{$Level}{$ASymbol} = 1;
11156 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11157 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011158 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011159 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 }
11162 }
11163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011164 }
11165 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011166 else
11167 { # Source-level
11168 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011169 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 next if($Interface eq $AddedVFunc);
11171 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011172 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11174 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011175 "Target"=>get_Signature($AddedVFunc, 2) );
11176 }
11177 }
11178 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11179 {
11180 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11181 {
11182 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11183 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011184 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011185 }
11186 }
11187 }
11188}
11189
11190sub find_MemberPair_Pos_byName($$)
11191{
11192 my ($Member_Name, $Pair_Type) = @_;
11193 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11194 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11195 {
11196 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11197 {
11198 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11199 $Name=~s/\A[_]+|[_]+\Z//g;
11200 if($Name eq $Member_Name) {
11201 return $MemberPair_Pos;
11202 }
11203 }
11204 }
11205 return "lost";
11206}
11207
11208sub find_MemberPair_Pos_byVal($$)
11209{
11210 my ($Member_Value, $Pair_Type) = @_;
11211 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11212 {
11213 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11214 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11215 return $MemberPair_Pos;
11216 }
11217 }
11218 return "lost";
11219}
11220
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011221sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011222{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011223 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011224 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011225 if( $_->{"T1"} eq $_[0]
11226 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011227 {
11228 return 1;
11229 }
11230 }
11231 return 0;
11232}
11233
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011234sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011235{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011236 my %IDs = (
11237 "T1" => $_[0],
11238 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011239 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011240 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011241}
11242
11243sub isRenamed($$$$$)
11244{
11245 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11246 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11247 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011248 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011249 if(not defined $Type2->{"Memb"}{$MemPos}) {
11250 return "";
11251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011252 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011253 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011254
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011255 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11256 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011257 if($MemberPair_Pos_Rev eq "lost")
11258 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011259 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11260 { # base type match
11261 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011263 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11264 { # exact type match
11265 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011267 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11268 { # size match
11269 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011271 if(isReserved($Pair_Name))
11272 { # reserved fields
11273 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011274 }
11275 }
11276 return "";
11277}
11278
11279sub isLastElem($$)
11280{
11281 my ($Pos, $TypeRef) = @_;
11282 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11283 if($Name=~/last|count|max|total/i)
11284 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11285 return 1;
11286 }
11287 elsif($Name=~/END|NLIMITS\Z/)
11288 { # __RLIMIT_NLIMITS
11289 return 1;
11290 }
11291 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11292 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11293 { # NImageFormats, NColorRoles
11294 return 1;
11295 }
11296 return 0;
11297}
11298
11299sub nonComparable($$)
11300{
11301 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011302
11303 my $N1 = $T1->{"Name"};
11304 my $N2 = $T2->{"Name"};
11305
11306 $N1=~s/\A(struct|union|enum) //;
11307 $N2=~s/\A(struct|union|enum) //;
11308
11309 if($N1 ne $N2
11310 and not isAnon($N1)
11311 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011312 { # different names
11313 if($T1->{"Type"} ne "Pointer"
11314 or $T2->{"Type"} ne "Pointer")
11315 { # compare base types
11316 return 1;
11317 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011318 if($N1!~/\Avoid\s*\*/
11319 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011320 {
11321 return 1;
11322 }
11323 }
11324 elsif($T1->{"Type"} ne $T2->{"Type"})
11325 { # different types
11326 if($T1->{"Type"} eq "Class"
11327 and $T2->{"Type"} eq "Struct")
11328 { # "class" to "struct"
11329 return 0;
11330 }
11331 elsif($T2->{"Type"} eq "Class"
11332 and $T1->{"Type"} eq "Struct")
11333 { # "struct" to "class"
11334 return 0;
11335 }
11336 else
11337 { # "class" to "enum"
11338 # "union" to "class"
11339 # ...
11340 return 1;
11341 }
11342 }
11343 return 0;
11344}
11345
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011346sub isOpaque($)
11347{
11348 my $T = $_[0];
11349 if(not defined $T->{"Memb"})
11350 {
11351 return 1;
11352 }
11353 return 0;
11354}
11355
11356sub removeVPtr($)
11357{ # support for old ABI dumps
11358 my $TPtr = $_[0];
11359 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11360 if($#Pos>=1)
11361 {
11362 foreach my $Pos (0 .. $#Pos-1)
11363 {
11364 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11365 }
11366 delete($TPtr->{"Memb"}{$#Pos});
11367 }
11368}
11369
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011370sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011371{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011372 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011373 return {} if(not $Type1_Id or not $Type2_Id);
11374
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011375 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011376 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011377 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011378 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011379
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011380 my %Type1 = get_Type($Type1_Id, 1);
11381 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011382 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011383 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011384 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011385
11386 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011387 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11388 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011389
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011390 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11391
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011392 my %SubProblems = ();
11393
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011394 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11395 {
11396 if($Type1_Pure{"Type"}=~/Struct|Union/
11397 and $Type2_Pure{"Type"}=~/Struct|Union/)
11398 {
11399 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11400 {
11401 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11402 "Target"=>$Type1_Pure{"Name"},
11403 "Type_Name"=>$Type1_Pure{"Name"} );
11404
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011405 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011406 }
11407 }
11408 }
11409
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011410 if(not $Type1_Pure{"Size"}
11411 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011412 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011413 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11414 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11415 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011416 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011417 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011418 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011419 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011420 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011421 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011422 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011423 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11424 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11425 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011426
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011427 if(defined $TargetHeadersPath)
11428 {
11429 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11430 return {};
11431 }
11432 }
11433
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011434 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11435 { # support for old ABI dumps
11436 # _vptr field added in 3.0
11437 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11438 {
11439 if(defined $Type2_Pure{"Memb"}
11440 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11441 {
11442 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11443 delete($Type2_Pure{"Memb"}{0});
11444 }
11445 else {
11446 removeVPtr(\%Type2_Pure);
11447 }
11448 }
11449 }
11450 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11451 {
11452 if(defined $Type1_Pure{"Memb"}
11453 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11454 {
11455 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11456 delete($Type1_Pure{"Memb"}{0});
11457 }
11458 else {
11459 removeVPtr(\%Type1_Pure);
11460 }
11461 }
11462 }
11463 }
11464
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011465 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11466 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011467
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011468 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011469 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11470 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011471 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011472 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11473 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011474 if($Base_1{"Name"} ne $Base_2{"Name"})
11475 {
11476 if(differentDumps("G")
11477 or differentDumps("V"))
11478 { # different GCC versions or different dumps
11479 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11480 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11481 # std::__va_list and __va_list
11482 $Base_1{"Name"}=~s/\A(\w+::)+//;
11483 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011484 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11485 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011487 }
11488 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11489 and $Base_1{"Name"} ne $Base_2{"Name"})
11490 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011491 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011492 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011493 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011494 {
11495 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11496 "Target"=>$Typedef_1{"Name"},
11497 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011498 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11499 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11500 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011501 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11502 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011503 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011504 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011505 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11506 {
11507 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11508 "Target"=>$Typedef_1{"Name"},
11509 "Type_Name"=>$Typedef_1{"Name"},
11510 "Old_Value"=>$Base_1{"Name"},
11511 "New_Value"=>$Base_2{"Name"} );
11512 }
11513 else
11514 {
11515 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11516 "Target"=>$Typedef_1{"Name"},
11517 "Type_Name"=>$Typedef_1{"Name"},
11518 "Old_Value"=>$Base_1{"Name"},
11519 "New_Value"=>$Base_2{"Name"} );
11520 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011522 }
11523 }
11524 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11525 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011526 my $TT1 = $Type1_Pure{"Type"};
11527 my $TT2 = $Type2_Pure{"Type"};
11528
11529 if($TT1 ne $TT2
11530 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011531 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011532 my $Short1 = $Type1_Pure{"Name"};
11533 my $Short2 = $Type2_Pure{"Name"};
11534
11535 $Short1=~s/\A\Q$TT1\E //ig;
11536 $Short2=~s/\A\Q$TT2\E //ig;
11537
11538 if($Short1 eq $Short2)
11539 {
11540 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11541 "Target"=>$Type1_Pure{"Name"},
11542 "Type_Name"=>$Type1_Pure{"Name"},
11543 "Old_Value"=>lc($Type1_Pure{"Type"}),
11544 "New_Value"=>lc($Type2_Pure{"Type"}) );
11545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011546 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011547 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011548 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011549 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011550 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11551 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11552 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11553 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011554 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011555 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011556 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011557 {
11558 my $ProblemKind = "DataType_Size";
11559 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011560 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011561 {
11562 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11563 $ProblemKind = "Size_Of_Copying_Class";
11564 }
11565 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11566 {
11567 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11568 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11569 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011570 else
11571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011572 # descreased size of allocable class
11573 # it has no special effects
11574 }
11575 }
11576 }
11577 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11578 "Target"=>$Type1_Pure{"Name"},
11579 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011580 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011581 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011582 }
11583 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011584 if(defined $Type1_Pure{"BaseType"}
11585 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011586 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011587 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11588 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011589 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011590 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11591 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011592 }
11593 }
11594 }
11595 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11596 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11597 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11598 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11599 { # detect removed and renamed fields
11600 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11601 next if(not $Member_Name);
11602 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);
11603 if($MemberPair_Pos eq "lost")
11604 {
11605 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11606 {
11607 if(isUnnamed($Member_Name))
11608 { # support for old-version dumps
11609 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011610 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011611 next;
11612 }
11613 }
11614 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11615 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011616 $RenamedField{$Member_Pos} = $RenamedTo;
11617 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011618 }
11619 else
11620 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011621 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011622 }
11623 }
11624 elsif($Type1_Pure{"Type"} eq "Enum")
11625 {
11626 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11627 next if($Member_Value1 eq "");
11628 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11629 if($MemberPair_Pos ne "lost")
11630 { # renamed
11631 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11632 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11633 if($MemberPair_Pos_Rev eq "lost")
11634 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011635 $RenamedField{$Member_Pos} = $RenamedTo;
11636 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011637 }
11638 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011639 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011640 }
11641 }
11642 else
11643 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011644 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 }
11646 }
11647 }
11648 else
11649 { # related
11650 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11651 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11652 }
11653 }
11654 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11655 { # detect added fields
11656 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11657 next if(not $Member_Name);
11658 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);
11659 if($MemberPair_Pos eq "lost")
11660 {
11661 if(isUnnamed($Member_Name))
11662 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011663 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011664 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 next;
11666 }
11667 }
11668 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11669 {
11670 if(not $RenamedField_Rev{$Member_Pos})
11671 { # added
11672 $AddedField{$Member_Pos}=1;
11673 }
11674 }
11675 }
11676 }
11677 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11678 { # detect moved fields
11679 my (%RelPos, %RelPosName, %AbsPos) = ();
11680 my $Pos = 0;
11681 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11682 { # relative positions in 1st version
11683 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11684 next if(not $Member_Name);
11685 if(not $RemovedField{$Member_Pos})
11686 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011687 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011688 $RelPosName{1}{$Pos} = $Member_Name;
11689 $AbsPos{1}{$Pos++} = $Member_Pos;
11690 }
11691 }
11692 $Pos = 0;
11693 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11694 { # relative positions in 2nd version
11695 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11696 next if(not $Member_Name);
11697 if(not $AddedField{$Member_Pos})
11698 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011699 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 $RelPosName{2}{$Pos} = $Member_Name;
11701 $AbsPos{2}{$Pos++} = $Member_Pos;
11702 }
11703 }
11704 foreach my $Member_Name (keys(%{$RelPos{1}}))
11705 {
11706 my $RPos1 = $RelPos{1}{$Member_Name};
11707 my $AbsPos1 = $NameToPosA{$Member_Name};
11708 my $Member_Name2 = $Member_Name;
11709 if(my $RenamedTo = $RenamedField{$AbsPos1})
11710 { # renamed
11711 $Member_Name2 = $RenamedTo;
11712 }
11713 my $RPos2 = $RelPos{2}{$Member_Name2};
11714 if($RPos2 ne "" and $RPos1 ne $RPos2)
11715 { # different relative positions
11716 my $AbsPos2 = $NameToPosB{$Member_Name2};
11717 if($AbsPos1 ne $AbsPos2)
11718 { # different absolute positions
11719 my $ProblemType = "Moved_Field";
11720 if(not isPublic(\%Type1_Pure, $AbsPos1))
11721 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011722 if($Level eq "Source") {
11723 next;
11724 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011725 $ProblemType = "Moved_Private_Field";
11726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011727 if($Level eq "Binary"
11728 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011730 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011731 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011732 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 if($MemSize1 ne $MemSize2) {
11734 $ProblemType .= "_And_Size";
11735 }
11736 }
11737 if($ProblemType eq "Moved_Private_Field") {
11738 next;
11739 }
11740 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11741 "Target"=>$Member_Name,
11742 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011743 "Old_Value"=>$RPos1,
11744 "New_Value"=>$RPos2 );
11745 }
11746 }
11747 }
11748 }
11749 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011750 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11752 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011753 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 if(my $RenamedTo = $RenamedField{$Member_Pos})
11755 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011756 if(defined $Constants{2}{$Member_Name})
11757 {
11758 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11759 { # define OLD NEW
11760 next; # Safe
11761 }
11762 }
11763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011764 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11765 {
11766 if(isPublic(\%Type1_Pure, $Member_Pos))
11767 {
11768 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11769 "Target"=>$Member_Name,
11770 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011771 "Old_Value"=>$Member_Name,
11772 "New_Value"=>$RenamedTo );
11773 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011774 elsif(isReserved($Member_Name))
11775 {
11776 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11777 "Target"=>$Member_Name,
11778 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011779 "Old_Value"=>$Member_Name,
11780 "New_Value"=>$RenamedTo );
11781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011782 }
11783 elsif($Type1_Pure{"Type"} eq "Enum")
11784 {
11785 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11786 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11787 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011788 "Old_Value"=>$Member_Name,
11789 "New_Value"=>$RenamedTo );
11790 }
11791 }
11792 elsif($RemovedField{$Member_Pos})
11793 { # removed
11794 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11795 {
11796 my $ProblemType = "Removed_Field";
11797 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011798 or isUnnamed($Member_Name))
11799 {
11800 if($Level eq "Source") {
11801 next;
11802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011803 $ProblemType = "Removed_Private_Field";
11804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011805 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011806 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011807 {
11808 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11809 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011810 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 +040011811 { # changed offset
11812 $ProblemType .= "_And_Layout";
11813 }
11814 }
11815 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11816 { # affected size
11817 $ProblemType .= "_And_Size";
11818 }
11819 }
11820 if($ProblemType eq "Removed_Private_Field") {
11821 next;
11822 }
11823 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11824 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011825 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011826 }
11827 elsif($Type2_Pure{"Type"} eq "Union")
11828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011829 if($Level eq "Binary"
11830 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011831 {
11832 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11833 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011834 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011835 }
11836 else
11837 {
11838 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11839 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011840 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011841 }
11842 }
11843 elsif($Type1_Pure{"Type"} eq "Enum")
11844 {
11845 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11846 "Target"=>$Member_Name,
11847 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848 "Old_Value"=>$Member_Name );
11849 }
11850 }
11851 else
11852 { # changed
11853 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11854 if($Type1_Pure{"Type"} eq "Enum")
11855 {
11856 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11857 next if($Member_Value1 eq "");
11858 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11859 next if($Member_Value2 eq "");
11860 if($Member_Value1 ne $Member_Value2)
11861 {
11862 my $ProblemType = "Enum_Member_Value";
11863 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11864 $ProblemType = "Enum_Last_Member_Value";
11865 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011866 if($SkipConstants{1}{$Member_Name}) {
11867 $ProblemType = "Enum_Private_Member_Value";
11868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011869 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11870 "Target"=>$Member_Name,
11871 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 "Old_Value"=>$Member_Value1,
11873 "New_Value"=>$Member_Value2 );
11874 }
11875 }
11876 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11877 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011878 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11879 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11880
11881 if($Access1 ne "private"
11882 and $Access2 eq "private")
11883 {
11884 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11885 "Target"=>$Member_Name,
11886 "Type_Name"=>$Type1_Pure{"Name"});
11887 }
11888 elsif($Access1 ne "protected"
11889 and $Access1 ne "private"
11890 and $Access2 eq "protected")
11891 {
11892 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11893 "Target"=>$Member_Name,
11894 "Type_Name"=>$Type1_Pure{"Name"});
11895 }
11896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011897 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11898 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011899 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011900 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11901 $SizeV1 = $BSize1;
11902 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011903 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011904 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11905 $SizeV2 = $BSize2;
11906 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011907 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11908 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011909 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011910 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011911 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011912 {
11913 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11914 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11915 { # field size change (including anon-structures and unions)
11916 # - same types
11917 # - unnamed types
11918 # - bitfields
11919 my $ProblemType = "Field_Size";
11920 if(not isPublic(\%Type1_Pure, $Member_Pos)
11921 or isUnnamed($Member_Name))
11922 { # should not be accessed by applications, goes to "Low Severity"
11923 # example: "abidata" members in GStreamer types
11924 $ProblemType = "Private_".$ProblemType;
11925 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011926 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 +040011927 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011928 if($Type2_Pure{"Type"} ne "Union"
11929 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011930 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011931 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 +040011932 { # changed offset
11933 $ProblemType .= "_And_Layout";
11934 }
11935 }
11936 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11937 $ProblemType .= "_And_Type_Size";
11938 }
11939 }
11940 if($ProblemType eq "Private_Field_Size")
11941 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011942 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011943 if($ProblemType eq "Field_Size")
11944 {
11945 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11946 { # Low severity
11947 $ProblemType = "Struct_Field_Size_Increased";
11948 }
11949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 if($ProblemType)
11951 { # register a problem
11952 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11953 "Target"=>$Member_Name,
11954 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 "Old_Size"=>$SizeV1,
11956 "New_Size"=>$SizeV2);
11957 }
11958 }
11959 }
11960 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11961 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11962 { # do NOT check bitfield type changes
11963 next;
11964 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011965 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011966 {
11967 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11968 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11969 {
11970 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11971 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011972 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011973 }
11974 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11975 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11976 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011977 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011978 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011979 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011980 }
11981 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011982 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
11983 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011984 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011985 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
11986 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011987
11988 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011989 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011990 or $ProblemType eq "Field_Type_And_Size"
11991 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011992 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011993 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011994 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011995 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011996 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011997 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011998 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011999 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012000 }
12001 }
12002 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12003 {
12004 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012005 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012006 }
12007 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012008 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012009 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012010 }
12011 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12012 {
12013 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012014 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012015 }
12016 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012017 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012019 }
12020 }
12021 }
12022
12023 if($Level eq "Source")
12024 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012025 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012026 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012027 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12028 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029
12030 if($ProblemType eq "Field_Type")
12031 {
12032 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012033 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012034 }
12035 }
12036 }
12037 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012038
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012039 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012040 {
12041 my $ProblemType_Init = $ProblemType;
12042 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012043 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 if(not isPublic(\%Type1_Pure, $Member_Pos)
12045 or isUnnamed($Member_Name)) {
12046 $ProblemType = "Private_".$ProblemType;
12047 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012048 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 +040012049 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012050 if($Type2_Pure{"Type"} ne "Union"
12051 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012052 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012053 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 +040012054 { # changed offset
12055 $ProblemType .= "_And_Layout";
12056 }
12057 }
12058 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12059 $ProblemType .= "_And_Type_Size";
12060 }
12061 }
12062 }
12063 else
12064 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012065 # TODO: Private_Field_Type rule?
12066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012067 if(not isPublic(\%Type1_Pure, $Member_Pos)
12068 or isUnnamed($Member_Name)) {
12069 next;
12070 }
12071 }
12072 if($ProblemType eq "Private_Field_Type_And_Size")
12073 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 }
12075 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12076 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012077 "Type_Name"=>$Type1_Pure{"Name"});
12078
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012079 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012081 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012082 }
12083 }
12084 if(not isPublic(\%Type1_Pure, $Member_Pos))
12085 { # do NOT check internal type changes
12086 next;
12087 }
12088 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012089 { # checking member type changes
12090 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12091
12092 my %DupProblems = ();
12093
12094 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012095 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012096 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012097 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012098 if(not defined $AllAffected)
12099 {
12100 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12101 next;
12102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012103 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012104
12105 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12106 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12107
12108 if(not defined $AllAffected)
12109 {
12110 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012111 }
12112 }
12113 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012114
12115 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012116 }
12117 }
12118 }
12119 }
12120 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12121 { # checking added members, public and private
12122 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12123 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012124 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012125 if($AddedField{$Member_Pos})
12126 { # added
12127 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12128 {
12129 my $ProblemType = "Added_Field";
12130 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012131 or isUnnamed($Member_Name))
12132 {
12133 if($Level eq "Source") {
12134 next;
12135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 $ProblemType = "Added_Private_Field";
12137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012138 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012139 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012140 {
12141 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12142 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012143 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 +040012144 { # changed offset
12145 $ProblemType .= "_And_Layout";
12146 }
12147 }
12148 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12149 $ProblemType .= "_And_Size";
12150 }
12151 }
12152 if($ProblemType eq "Added_Private_Field")
12153 { # skip added private fields
12154 next;
12155 }
12156 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12157 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012158 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012159 }
12160 elsif($Type2_Pure{"Type"} eq "Union")
12161 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012162 if($Level eq "Binary"
12163 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012164 {
12165 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12166 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012167 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012168 }
12169 else
12170 {
12171 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12172 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012173 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012174 }
12175 }
12176 elsif($Type2_Pure{"Type"} eq "Enum")
12177 {
12178 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12179 next if($Member_Value eq "");
12180 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12181 "Target"=>$Member_Name,
12182 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012183 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 }
12185 }
12186 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012188 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012189 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012190}
12191
12192sub isUnnamed($) {
12193 return $_[0]=~/\Aunnamed\d+\Z/;
12194}
12195
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012196sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012197{
12198 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012199 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12200 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12201 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012203 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012204 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012205 }
12206 return $TypeName;
12207}
12208
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012209sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012210{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012211 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012212 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012213 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12214 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012216 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12217 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 return () if(not $Type{"Type"});
12219 if($Type{"Type"} ne $Type_Type)
12220 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012221 return () if(not $Type{"BaseType"});
12222 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012223 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012224 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 return %Type;
12226}
12227
12228my %TypeSpecAttributes = (
12229 "Const" => 1,
12230 "Volatile" => 1,
12231 "ConstVolatile" => 1,
12232 "Restrict" => 1,
12233 "Typedef" => 1
12234);
12235
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012237{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012238 my ($TypeId, $Info) = @_;
12239 if(not $TypeId or not $Info
12240 or not $Info->{$TypeId}) {
12241 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012243 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12244 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12245 }
12246 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012247 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012249 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012251 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 return %Type;
12253}
12254
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012255sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012257 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012259 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12260 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012262 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12263 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012264 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12265 my $PLevel = 0;
12266 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12267 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012269 return $PLevel if(not $Type{"BaseType"});
12270 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12271 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12272 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012273}
12274
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012275sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012277 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012278 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012279 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12280 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012282 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12283 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012284 return %Type if(not $Type{"BaseType"});
12285 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012286 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012287 return %Type;
12288}
12289
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012290sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012292 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012294 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12295 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012296 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012297 my $Qual = "";
12298 if($Type{"Type"} eq "Pointer") {
12299 $Qual .= "*";
12300 }
12301 elsif($Type{"Type"} eq "Ref") {
12302 $Qual .= "&";
12303 }
12304 elsif($Type{"Type"} eq "ConstVolatile") {
12305 $Qual .= "const volatile";
12306 }
12307 elsif($Type{"Type"} eq "Const"
12308 or $Type{"Type"} eq "Volatile"
12309 or $Type{"Type"} eq "Restrict") {
12310 $Qual .= lc($Type{"Type"});
12311 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012312 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 return $BQual.$Qual;
12314}
12315
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012316sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012318 my ($TypeId, $Info) = @_;
12319 if(not $TypeId or not $Info
12320 or not $Info->{$TypeId}) {
12321 return ();
12322 }
12323 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012324 return %Type if(not $Type{"BaseType"});
12325 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012326 {
12327 if($Info->{$BTid}) {
12328 return %{$Info->{$BTid}};
12329 }
12330 else { # something is going wrong
12331 return ();
12332 }
12333 }
12334 else {
12335 return %Type;
12336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337}
12338
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012339sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012340{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012341 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012342 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012343 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12344 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012345}
12346
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012347sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012348{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012349 my $Symbol = $_[0];
12350 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12351}
12352
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012353sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012354 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12355}
12356
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012357sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012359 my ($SInfo, $LibVersion) = @_;
12360
12361 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012362 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012363 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012364 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012365 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012366 return 1;
12367 }
12368 }
12369 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012370 if(my $ShortName = $SInfo->{"ShortName"})
12371 {
12372 if(index($ShortName,"<")!=-1
12373 and index($ShortName,">")!=-1) {
12374 return 1;
12375 }
12376 }
12377
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012378 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012379}
12380
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012381sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012383 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012384 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012387 { # class specialization
12388 return 1;
12389 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012390 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391 { # method specialization
12392 return 1;
12393 }
12394 }
12395 return 0;
12396}
12397
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012398sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012400 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012401
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012402 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403 { # non-public global data
12404 return 0;
12405 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012406
12407 if(defined $SkipInternal)
12408 {
12409 return 0 if($Symbol=~/($SkipInternal)/);
12410 }
12411
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012412 if($Symbol=~/\A_Z/)
12413 {
12414 if($Symbol=~/[CD][3-4]E/) {
12415 return 0;
12416 }
12417 }
12418
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012419 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420 { # support for old ABI dumps in --headers-only mode
12421 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12422 {
12423 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12424 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012425 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426 if(not $PType or $PType eq "Unknown") {
12427 return 0;
12428 }
12429 }
12430 }
12431 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012432 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012434 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12435
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 if($SkipSymbols{$LibVersion}{$Symbol})
12437 { # user defined symbols to ignore
12438 return 0;
12439 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012440
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012441 if($SymbolsListPath and not $SymbolsList{$Symbol})
12442 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012443 if(not $TargetHeadersPath or not $Header
12444 or not is_target_header($Header, 1))
12445 { # -symbols-list | -headers-list
12446 return 0;
12447 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012448 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012449
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012450 if($AppPath and not $SymbolsList_App{$Symbol})
12451 { # user defined symbols (in application)
12452 return 0;
12453 }
12454
12455 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12458 if(not $NameSpace and $ClassId)
12459 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012460 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461 }
12462 if($NameSpace)
12463 { # user defined namespaces to ignore
12464 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12465 return 0;
12466 }
12467 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12468 { # nested namespaces
12469 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12470 return 0;
12471 }
12472 }
12473 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012474 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012475 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012476 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012477 { # --skip-headers or <skip_headers> (not <skip_including>)
12478 if($Skip==1) {
12479 return 0;
12480 }
12481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012482 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012483 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012484 { # user defined types
12485 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12486
12487 if(not $TypesList{$CName})
12488 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012489 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12490 {
12491 $CName=~s/\A\Q$NS\E\:\://g;
12492 }
12493
12494 if(not $TypesList{$CName})
12495 {
12496 my $Found = 0;
12497
12498 while($CName=~s/\:\:.+?\Z//)
12499 {
12500 if($TypesList{$CName})
12501 {
12502 $Found = 1;
12503 last;
12504 }
12505 }
12506
12507 if(not $Found) {
12508 return 0;
12509 }
12510 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012511 }
12512 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012513
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012514 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12515 { # non-target symbols
12516 return 0;
12517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012518 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012520 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12521 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012522 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012523 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12524 { # inline virtual methods
12525 if($Type=~/InlineVirt/) {
12526 return 1;
12527 }
12528 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12529 if(not $Allocable)
12530 { # check bases
12531 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12532 {
12533 if(not isCopyingClass($DCId, $LibVersion))
12534 { # exists a derived class without default c-tor
12535 $Allocable=1;
12536 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012538 }
12539 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012540 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012541 return 0;
12542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012544 else
12545 { # inline non-virtual methods
12546 return 0;
12547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549 }
12550 }
12551 return 1;
12552}
12553
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012554sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012556 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012557 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12558 {
12559 if(link_symbol($Symbol, 1, "+Deps"))
12560 { # linker can find a new symbol
12561 # in the old-version library
12562 # So, it's not a new symbol
12563 next;
12564 }
12565 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012566 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567 next;
12568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012569 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 }
12571}
12572
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012573sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012574{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012575 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12577 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 if(link_symbol($Symbol, 2, "+Deps"))
12579 { # linker can find an old symbol
12580 # in the new-version library
12581 next;
12582 }
12583 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012584 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585 next;
12586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012587 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 }
12589}
12590
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012591sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012592{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012593 my $Level = $_[0];
12594 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595 { # checking added symbols
12596 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012597 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012598 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012599 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012601 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 { # checking removed symbols
12603 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012604 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012605 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 { # skip v-tables for templates, that should not be imported by applications
12607 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012608 if(my $CName = $VTableClass{$Symbol})
12609 {
12610 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12611 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012612 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012613 next;
12614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 }
12616 }
12617 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012618 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012619 }
12620 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12621 { # symbols for pure virtual methods cannot be called by clients
12622 next;
12623 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012624 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 }
12626}
12627
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012628sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012629{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012630 my ($LibVersion, $V) = @_;
12631 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12632 return $Cache{"checkDump"}{$LibVersion}{$V};
12633 }
12634 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012635}
12636
12637sub detectAdded_H($)
12638{
12639 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012642 if($Level eq "Source")
12643 { # remove symbol version
12644 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12645 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012646
12647 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12648 { # skip artificial constructors
12649 next;
12650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012651 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012652 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12653 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012654 next;
12655 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012656 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657 next;
12658 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012659 if(not defined $CompleteSignature{1}{$Symbol}
12660 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12661 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012662 if($UsedDump{2}{"SrcBin"})
12663 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012664 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012665 { # support for old and different (!) ABI dumps
12666 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12667 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012668 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012669 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012670 {
12671 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12672 {
12673 if($Lang eq "C")
12674 { # support for old ABI dumps: missed extern "C" functions
12675 next;
12676 }
12677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012678 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012679 else
12680 {
12681 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012682 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012683 next;
12684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012685 }
12686 }
12687 }
12688 }
12689 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012690 }
12691 }
12692}
12693
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012694sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012695{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012696 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012697 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12698 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012699 if($Level eq "Source")
12700 { # remove symbol version
12701 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12702 $Symbol=$SN;
12703 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012704 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12705 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012706 next;
12707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012708 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012709 next;
12710 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012711 if(not defined $CompleteSignature{2}{$Symbol}
12712 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012713 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012714 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012716 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012717 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012718 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12719 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012720 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012721 if($CheckHeadersOnly)
12722 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012723 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12724 {
12725 if($Lang eq "C")
12726 { # support for old ABI dumps: missed extern "C" functions
12727 next;
12728 }
12729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012730 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012731 else
12732 {
12733 if(not link_symbol($Symbol, 1, "-Deps"))
12734 { # skip removed inline symbols
12735 next;
12736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012737 }
12738 }
12739 }
12740 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012741 if(not checkDump(1, "2.15"))
12742 {
12743 if($Symbol=~/_IT_E\Z/)
12744 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12745 next;
12746 }
12747 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012748 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12749 {
12750 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12751 {
12752 if(defined $Constants{2}{$Short})
12753 {
12754 my $Val = $Constants{2}{$Short}{"Value"};
12755 if(defined $Func_ShortName{2}{$Val})
12756 { # old name defined to new
12757 next;
12758 }
12759 }
12760 }
12761
12762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012763 $RemovedInt{$Level}{$Symbol} = 1;
12764 if($Level eq "Source")
12765 { # search for a source-compatible equivalent
12766 setAlternative($Symbol, $Level);
12767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 }
12769 }
12770}
12771
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012772sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 my $Level = $_[0];
12775 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012776 { # checking added symbols
12777 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012778 next if($CompleteSignature{2}{$Symbol}{"Private"});
12779 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012780 if($Level eq "Binary")
12781 {
12782 if($CompleteSignature{2}{$Symbol}{"InLine"})
12783 {
12784 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12785 { # skip inline non-virtual functions
12786 next;
12787 }
12788 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012789 }
12790 else
12791 { # Source
12792 if($SourceAlternative_B{$Symbol}) {
12793 next;
12794 }
12795 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012796 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012798 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012799 { # checking removed symbols
12800 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012801 next if($CompleteSignature{1}{$Symbol}{"Private"});
12802 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012803 if($Level eq "Binary")
12804 {
12805 if($CompleteSignature{1}{$Symbol}{"InLine"})
12806 {
12807 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12808 { # skip inline non-virtual functions
12809 next;
12810 }
12811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 }
12813 else
12814 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012815 if(my $Alt = $SourceAlternative{$Symbol})
12816 {
12817 if(defined $CompleteSignature{1}{$Alt}
12818 and $CompleteSignature{1}{$Symbol}{"Const"})
12819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012820 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012821 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012822 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012823 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012824 }
12825 else
12826 { # do NOT show removed symbol
12827 next;
12828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012829 }
12830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832 }
12833}
12834
12835sub addParamNames($)
12836{
12837 my $LibraryVersion = $_[0];
12838 return if(not keys(%AddIntParams));
12839 my $SecondVersion = $LibraryVersion==1?2:1;
12840 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12841 {
12842 next if(not keys(%{$AddIntParams{$Interface}}));
12843 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012844 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12846 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012847 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12849 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12850 {
12851 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12852 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12853 }
12854 }
12855 else {
12856 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12857 }
12858 }
12859 }
12860 }
12861}
12862
12863sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012864{ # detect changed typedefs to show
12865 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12867 {
12868 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012869 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12870 if(not $BName1 or isAnon($BName1)) {
12871 next;
12872 }
12873 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12874 if(not $BName2 or isAnon($BName2)) {
12875 next;
12876 }
12877 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878 $ChangedTypedef{$Typedef} = 1;
12879 }
12880 }
12881}
12882
12883sub get_symbol_suffix($$)
12884{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012885 my ($Symbol, $Full) = @_;
12886 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012887 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012888 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012889 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 if(not $Full) {
12891 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12892 }
12893 return $Suffix;
12894}
12895
12896sub get_symbol_prefix($$)
12897{
12898 my ($Symbol, $LibVersion) = @_;
12899 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12900 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12901 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012902 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012903 }
12904 return $ShortName;
12905}
12906
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012907sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012908{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012909 my $Symbol = $_[0];
12910 my $PSymbol = $Symbol;
12911 if(not defined $CompleteSignature{2}{$PSymbol}
12912 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12913 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12914 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012915 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012917 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012918 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012919 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12920 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012921 {
12922 if(defined $CompleteSignature{2}{$PSymbol}
12923 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12924 {
12925 $SourceAlternative{$Symbol} = $PSymbol;
12926 $SourceAlternative_B{$PSymbol} = $Symbol;
12927 if(not defined $CompleteSignature{1}{$PSymbol}
12928 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12929 $SourceReplacement{$Symbol} = $PSymbol;
12930 }
12931 }
12932 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012933 }
12934 else
12935 {
12936 foreach my $Sp ("KV", "VK", "K", "V")
12937 {
12938 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12939 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12940 {
12941 if(defined $CompleteSignature{2}{$PSymbol}
12942 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12943 {
12944 $SourceAlternative{$Symbol} = $PSymbol;
12945 $SourceAlternative_B{$PSymbol} = $Symbol;
12946 if(not defined $CompleteSignature{1}{$PSymbol}
12947 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12948 $SourceReplacement{$Symbol} = $PSymbol;
12949 }
12950 }
12951 }
12952 $PSymbol = $Symbol;
12953 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012954 }
12955 }
12956 }
12957 return "";
12958}
12959
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012960sub getSymKind($$)
12961{
12962 my ($Symbol, $LibVersion) = @_;
12963 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12964 {
12965 return "Global_Data";
12966 }
12967 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12968 {
12969 return "Method";
12970 }
12971 return "Function";
12972}
12973
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012974sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012975{
12976 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012977 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012978
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 mergeBases($Level);
12980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012981 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012983 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012985 next;
12986 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012987 if(defined $CompleteSignature{1}{$Symbol}
12988 and $CompleteSignature{1}{$Symbol}{"Header"})
12989 { # double-check added symbol
12990 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012991 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012992 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012993 next;
12994 }
12995 if($Symbol=~/\A(_Z|\?)/)
12996 { # C++
12997 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12998 }
12999 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13000 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013001 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13002 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013003 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013004 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013005 {
13006 if($TName_Tid{1}{$AffectedClass_Name})
13007 { # class should exist in previous version
13008 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13009 { # old v-table is NOT copied by old applications
13010 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13011 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013012 "Target"=>get_Signature($Symbol, 2),
13013 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013014 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 }
13018 }
13019 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013020 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13021 { # check all removed exported symbols
13022 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013023 next;
13024 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013025 if(defined $CompleteSignature{2}{$Symbol}
13026 and $CompleteSignature{2}{$Symbol}{"Header"})
13027 { # double-check removed symbol
13028 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013029 }
13030 if($CompleteSignature{1}{$Symbol}{"Private"})
13031 { # skip private methods
13032 next;
13033 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013034 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013035 next;
13036 }
13037 $CheckedSymbols{$Level}{$Symbol} = 1;
13038 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13039 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013040 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13041 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013042 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013043 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13044 {
13045 if($TName_Tid{2}{$AffectedClass_Name})
13046 { # class should exist in newer version
13047 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13048 { # old v-table is NOT copied by old applications
13049 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13050 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013051 "Target"=>get_Signature($OverriddenMethod, 1),
13052 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013053 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013056 }
13057 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013058 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013059 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013060 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013061 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013063 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013064 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013065 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013067 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013068 {
13069 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13070 "Target"=>$tr_name{$Symbol},
13071 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013072 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013073 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013074 else
13075 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013076 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013077 "Target"=>$tr_name{$Symbol},
13078 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013079 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013080 }
13081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013082 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013084 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 {
13086 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13087 "Target"=>$tr_name{$Symbol},
13088 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013089 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013090 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013091 else
13092 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013093 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 "Target"=>$tr_name{$Symbol},
13095 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013096 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013097 }
13098 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013099 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13100 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13101 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13102 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13103 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013104 {
13105 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013107 $ProblemType = "Global_Data_Symbol_Changed_Type";
13108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13110 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013111 "Old_Type"=>$RTName1,
13112 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013114 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013115 }
13116 }
13117 }
13118 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013119 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013121 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013122 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013123 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013124 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013125 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013126 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13127 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013128 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013129 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013130 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013131 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013132 }
13133 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13135 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013136 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013138 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013139 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013140 }
13141 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013142 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013143 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013144 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013145 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013147 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013148 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013149 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013150 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013152 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013154 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013155 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013157 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013158 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013159 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013160 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013161 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013162 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013163 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013165 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013166 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013167 { # "volatile" to non-"volatile"
13168
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013169 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013171 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013173 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013176 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013178 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013179 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013180 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013182 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013183 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013184 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13187 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013188 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013190 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 }
13192 }
13193 }
13194 }
13195 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013196 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13197 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013198 $CurrentSymbol = $Symbol;
13199
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13201 if($Level eq "Source")
13202 { # remove symbol version
13203 $Symbol=$SN;
13204 }
13205 else
13206 { # Binary
13207 if(not $SV)
13208 { # symbol without version
13209 if(my $VSym = $SymVer{1}{$Symbol})
13210 { # the symbol is linked with versioned symbol
13211 if($CompleteSignature{2}{$VSym}{"MnglName"})
13212 { # show report for symbol@ver only
13213 next;
13214 }
13215 elsif(not link_symbol($VSym, 2, "-Deps"))
13216 { # changed version: sym@v1 to sym@v2
13217 # do NOT show report for symbol
13218 next;
13219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013220 }
13221 }
13222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013223 my $PSymbol = $Symbol;
13224 if($Level eq "Source"
13225 and my $S = $SourceReplacement{$Symbol})
13226 { # take a source-compatible replacement function
13227 $PSymbol = $S;
13228 }
13229 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013230 { # private symbols
13231 next;
13232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 if(not defined $CompleteSignature{1}{$Symbol}
13234 or not defined $CompleteSignature{2}{$PSymbol})
13235 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013236 next;
13237 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013238 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13239 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13240 { # no mangled name
13241 next;
13242 }
13243 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13244 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 { # without a header
13246 next;
13247 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013248
13249 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13250 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13251 { # became pure
13252 next;
13253 }
13254 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13255 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13256 { # became non-pure
13257 next;
13258 }
13259
13260 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13261 { # exported, target, inline virtual and pure virtual
13262 next;
13263 }
13264 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13265 { # exported, target, inline virtual and pure virtual
13266 next;
13267 }
13268
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013270 {
13271 if($CompleteSignature{1}{$Symbol}{"Data"}
13272 and $CompleteSignature{2}{$PSymbol}{"Data"})
13273 {
13274 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13275 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13276 if(defined $Value1)
13277 {
13278 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13279 if(defined $Value2)
13280 {
13281 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13282 if($Value1 ne $Value2)
13283 {
13284 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13285 "Old_Value"=>$Value1,
13286 "New_Value"=>$Value2,
13287 "Target"=>get_Signature($Symbol, 1) );
13288 }
13289 }
13290 }
13291 }
13292 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013293
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013294 if($CompleteSignature{2}{$PSymbol}{"Private"})
13295 {
13296 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13297 "Target"=>get_Signature_M($PSymbol, 2) );
13298 }
13299 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13300 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13301 {
13302 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13303 "Target"=>get_Signature_M($PSymbol, 2) );
13304 }
13305 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13306 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13307 {
13308 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13309 "Target"=>get_Signature_M($PSymbol, 2) );
13310 }
13311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013312 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013313 mergeVirtualTables($Symbol, $Level);
13314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 if($COMPILE_ERRORS)
13316 { # if some errors occurred at the compiling stage
13317 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013318 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013319 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 { # missed information about parameters in newer version
13321 next;
13322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013323 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013324 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013325 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 next;
13327 }
13328 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013331 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013332 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13333 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13335 "Target"=>get_Signature($Symbol, 1)
13336 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013339 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13340 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013341 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 "Target"=>get_Signature($Symbol, 1)
13343 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13346 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013349 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013350 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13351 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13352 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013355 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13356 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013357 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013358 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 my $ProblemType = "Virtual_Method_Position";
13360 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13361 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 if(isUsedClass($Class_Id, 1, $Level))
13364 {
13365 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013366 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013368 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13369 next;
13370 }
13371 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13374 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013375 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013377 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 }
13380 }
13381 }
13382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13384 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 { # do NOT check type changes in pure virtuals
13386 next;
13387 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013388 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 if($Symbol=~/\A(_Z|\?)/
13390 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013394 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013395 }
13396 }
13397 else
13398 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013400 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013401 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013402 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13403 last if($PType2_Name eq "...");
13404 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13405 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013406 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013407 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013409 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13410 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13412 $ParamPos_Prev = "lost";
13413 }
13414 }
13415 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013416 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013417 }
13418 if($ParamPos_Prev eq "lost")
13419 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013420 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421 {
13422 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013423 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 $ProblemType = "Added_Unnamed_Parameter";
13425 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013426 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013427 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013428 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013429 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013431 }
13432 else
13433 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013434 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013435 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013436 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13438 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013439 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013440 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013441 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013442 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013443 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013444 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013445 "Param_Type"=>$PType2_Name,
13446 "Old_Value"=>$PName_Old,
13447 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013448 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013449 }
13450 }
13451 else
13452 {
13453 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 $ProblemType = "Added_Middle_Unnamed_Parameter";
13456 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013457 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013458 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013459 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013460 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013461 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 }
13463 }
13464 }
13465 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013466 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013467 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013468 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013469 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013470 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013471 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013472 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013473 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13476 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013477 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013478 }
13479 }
13480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013481 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013482 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013483 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013484 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13485 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013486 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13487 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013488 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013489 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013490 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013491 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13492 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013493 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13494 $ParamPos_New = "lost";
13495 }
13496 }
13497 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013498 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 }
13500 if($ParamPos_New eq "lost")
13501 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013502 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013503 {
13504 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013505 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 $ProblemType = "Removed_Unnamed_Parameter";
13507 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013508 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013509 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013510 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013511 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013516 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013517 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013518 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013519 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013520 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013521 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013522 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013524 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013525 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013526 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013527 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013528 "Old_Value"=>$PName,
13529 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 }
13532 }
13533 else
13534 {
13535 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013536 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013537 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13538 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013539 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013540 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013541 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013542 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013543 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013544 }
13545 }
13546 }
13547 }
13548 }
13549 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013550 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13551 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013552 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013553
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013554 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013555 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013556 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13557 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013558 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013559
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013560 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013562 if($SubProblemType eq "Return_Type_And_Size") {
13563 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13564 }
13565 elsif($SubProblemType eq "Return_Type_Format") {
13566 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13567 }
13568 else {
13569 $ProblemTypes{"Global_Data_Type"} = 1;
13570 }
13571
13572 # quals
13573 if($SubProblemType eq "Return_Type"
13574 or $SubProblemType eq "Return_Type_And_Size"
13575 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013577 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13578 { # const to non-const
13579 if($RR==2) {
13580 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13581 }
13582 else {
13583 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13584 }
13585 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013586 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013587 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13588 { # non-const to const
13589 if($RA==2) {
13590 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13591 }
13592 else {
13593 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13594 }
13595 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 }
13597 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013598 }
13599 else
13600 {
13601 # quals
13602 if($SubProblemType eq "Return_Type"
13603 or $SubProblemType eq "Return_Type_And_Size"
13604 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013606 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013607 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013608 if(addedQual($Old_Value, $New_Value, "volatile"))
13609 {
13610 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13611 if($Level ne "Source"
13612 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13613 $ProblemTypes{"Return_Type"} = 1;
13614 }
13615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013617 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13618 {
13619 if($RA==2) {
13620 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13621 }
13622 else {
13623 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13624 }
13625 if($Level ne "Source"
13626 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13627 $ProblemTypes{"Return_Type"} = 1;
13628 }
13629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 }
13631 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013632 if($Level eq "Binary"
13633 and not $CompleteSignature{1}{$Symbol}{"Data"})
13634 {
13635 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13636 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13637 { # if one of the architectures is unknown
13638 # then set other arhitecture to unknown too
13639 ($Arch1, $Arch2) = ("unknown", "unknown");
13640 }
13641 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013642 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013643 {
13644 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13645 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13646 }
13647 else
13648 {
13649 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13650 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13651 }
13652
13653 if($SubProblemType eq "Return_Type_Became_Void")
13654 {
13655 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13656 { # parameters stack has been affected
13657 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013658 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013659 }
13660 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013661 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013662 }
13663 }
13664 }
13665 elsif($SubProblemType eq "Return_Type_From_Void")
13666 {
13667 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13668 { # parameters stack has been affected
13669 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013670 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013671 }
13672 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013673 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013674 }
13675 }
13676 }
13677 elsif($SubProblemType eq "Return_Type"
13678 or $SubProblemType eq "Return_Type_And_Size"
13679 or $SubProblemType eq "Return_Type_Format")
13680 {
13681 if($Conv1{"Method"} ne $Conv2{"Method"})
13682 {
13683 if($Conv1{"Method"} eq "stack")
13684 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013685 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013686 }
13687 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013688 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013689 }
13690 }
13691 else
13692 {
13693 if($Conv1{"Method"} eq "reg")
13694 {
13695 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13696 {
13697 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013698 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013699 }
13700 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013701 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013702 }
13703 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013704 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013705 }
13706 }
13707 }
13708 }
13709 }
13710 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013711
13712 if(not keys(%ProblemTypes))
13713 { # default
13714 $ProblemTypes{$SubProblemType} = 1;
13715 }
13716
13717 foreach my $ProblemType (keys(%ProblemTypes))
13718 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013719 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013721 }
13722 if($ReturnType1_Id and $ReturnType2_Id)
13723 {
13724 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013725 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13726
13727 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013728
13729 if($CompleteSignature{1}{$Symbol}{"Data"})
13730 {
13731 if($Level eq "Binary")
13732 {
13733 if(get_PLevel($ReturnType1_Id, 1)==0)
13734 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013735 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013736 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013737
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013738 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13739 {
13740 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013741 {
13742 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13743 {
13744 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13745 last;
13746 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013747 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013748 }
13749 }
13750 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013751 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013752 {
13753 if(defined $GlobalDataObject{1}{$Symbol}
13754 and defined $GlobalDataObject{2}{$Symbol})
13755 {
13756 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13757 my $New_Size = $GlobalDataObject{2}{$Symbol};
13758 if($Old_Size!=$New_Size)
13759 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013760 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013761 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013762 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013763 }
13764 }
13765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013766 }
13767 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013768
13769 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013771 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013773 my $NewLocation = "retval";
13774 if($SubLocation and $SubLocation ne "retval") {
13775 $NewLocation = "retval->".$SubLocation;
13776 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013777 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13778 }
13779 }
13780
13781 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13782 {
13783 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13784 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013785 my $NewLocation = "retval";
13786 if($SubLocation and $SubLocation ne "retval") {
13787 $NewLocation = "retval->".$SubLocation;
13788 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013789 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 }
13791 }
13792 }
13793
13794 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013795 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13796 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13797 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013798 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013800 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13801 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 if($ThisPtr1_Id and $ThisPtr2_Id)
13803 {
13804 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013805 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13806 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013807 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013808 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 {
13810 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013811 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 }
13813 }
13814 }
13815 }
13816 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013817 if($Level eq "Binary") {
13818 mergeVTables($Level);
13819 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013820 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13821 $CheckedSymbols{$Level}{$Symbol} = 1;
13822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013823}
13824
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013825sub rmQuals($$)
13826{
13827 my ($Value, $Qual) = @_;
13828 if(not $Qual) {
13829 return $Value;
13830 }
13831 if($Qual eq "all")
13832 { # all quals
13833 $Qual = "const|volatile|restrict";
13834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013835 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013836 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013837 }
13838 return $Value;
13839}
13840
13841sub cmpBTypes($$$$)
13842{
13843 my ($T1, $T2, $V1, $V2) = @_;
13844 $T1 = uncover_typedefs($T1, $V1);
13845 $T2 = uncover_typedefs($T2, $V2);
13846 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13847}
13848
13849sub addedQual($$$)
13850{
13851 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013852 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013853}
13854
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013855sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013856{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013857 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013859}
13860
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013862{
13863 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13864 $Old_Value = uncover_typedefs($Old_Value, $V1);
13865 $New_Value = uncover_typedefs($New_Value, $V2);
13866 if($Old_Value eq $New_Value)
13867 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013868 return 0;
13869 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013870 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013871 { # without a qual
13872 return 0;
13873 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013874 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013875 { # became non-qual
13876 return 1;
13877 }
13878 else
13879 {
13880 my @BQ1 = getQualModel($Old_Value, $Qual);
13881 my @BQ2 = getQualModel($New_Value, $Qual);
13882 foreach (0 .. $#BQ1)
13883 { # removed qual
13884 if($BQ1[$_]==1
13885 and $BQ2[$_]!=1)
13886 {
13887 return 2;
13888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013889 }
13890 }
13891 return 0;
13892}
13893
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013894sub getQualModel($$)
13895{
13896 my ($Value, $Qual) = @_;
13897 if(not $Qual) {
13898 return $Value;
13899 }
13900
13901 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013902 while($Value=~/(\w+)/ and $1 ne $Qual) {
13903 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013904 }
13905 $Value=~s/[^\*\&\w]+//g;
13906
13907 # modeling
13908 # int*const*const == 011
13909 # int**const == 001
13910 my @Model = ();
13911 my @Elems = split(/[\*\&]/, $Value);
13912 if(not @Elems) {
13913 return (0);
13914 }
13915 foreach (@Elems)
13916 {
13917 if($_ eq $Qual) {
13918 push(@Model, 1);
13919 }
13920 else {
13921 push(@Model, 0);
13922 }
13923 }
13924
13925 return @Model;
13926}
13927
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013928my %StringTypes = map {$_=>1} (
13929 "char*",
13930 "char const*"
13931);
13932
13933my %CharTypes = map {$_=>1} (
13934 "char",
13935 "char const"
13936);
13937
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013938sub showVal($$$)
13939{
13940 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013941 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013942 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013943 if(substr($Value, 0, 2) eq "_Z")
13944 {
13945 if(my $Unmangled = $tr_name{$Value}) {
13946 return $Unmangled;
13947 }
13948 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013949 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013950 { # strings
13951 return "\"$Value\"";
13952 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013953 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013954 { # characters
13955 return "\'$Value\'";
13956 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013957 if($Value eq "")
13958 { # other
13959 return "\'\'";
13960 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013961 return $Value;
13962}
13963
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013964sub getRegs($$$)
13965{
13966 my ($LibVersion, $Symbol, $Pos) = @_;
13967
13968 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13969 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013970 my %Regs = ();
13971 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13972 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013973 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013974 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13975 }
13976 }
13977
13978 return join(", ", sort keys(%Regs));
13979 }
13980
13981 return undef;
13982}
13983
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013984sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013985{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013986 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013987 if(not $Symbol) {
13988 return;
13989 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013990 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13991 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13992 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13993 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013994 if(not $PType1_Id
13995 or not $PType2_Id) {
13996 return;
13997 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013998
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013999 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014000 { # do not merge "this"
14001 if($PName1 eq "this" or $PName2 eq "this") {
14002 return;
14003 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014004 }
14005
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014006 my %Type1 = get_Type($PType1_Id, 1);
14007 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014008
14009 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14010
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014011 my %BaseType1 = get_BaseType($PType1_Id, 1);
14012 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014013
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014014 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014015
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014016 if($Level eq "Binary")
14017 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014018 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014019 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14020 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14021 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14022 {
14023 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014024 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014025 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014026 }
14027 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14028 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14029 {
14030 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014031 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014032 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014034 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014035
14036 if(defined $UsedDump{1}{"DWARF"}
14037 and defined $UsedDump{2}{"DWARF"})
14038 {
14039 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14040 {
14041 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14042 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14043 if($Old_Regs and $New_Regs)
14044 {
14045 if($Old_Regs ne $New_Regs)
14046 {
14047 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14048 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014049 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014050 "Old_Value"=>$Old_Regs,
14051 "New_Value"=>$New_Regs );
14052 }
14053 }
14054 elsif($Old_Regs and not $New_Regs)
14055 {
14056 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14057 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014058 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014059 "Old_Value"=>$Old_Regs );
14060 }
14061 elsif(not $Old_Regs and $New_Regs)
14062 {
14063 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14064 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014065 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014066 "New_Value"=>$New_Regs );
14067 }
14068 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14069 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14070 {
14071 if($Old_Offset ne $New_Offset)
14072 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014073 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14074 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14075
14076 $Old_Offset = $Old_Offset - $Start1;
14077 $New_Offset = $New_Offset - $Start2;
14078
14079 if($Old_Offset ne $New_Offset)
14080 {
14081 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14082 "Target"=>$PName1,
14083 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14084 "Old_Value"=>$Old_Offset,
14085 "New_Value"=>$New_Offset );
14086 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014087 }
14088 }
14089 }
14090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014091 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014092 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14093 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014094 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014095 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014096 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14097 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014098 if(not checkDump(1, "2.13")
14099 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014100 { # support for old ABI dumps
14101 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014102 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014103 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014104 and $Value_Old eq "false" and $Value_New eq "0")
14105 { # int class::method ( bool p = 0 );
14106 # old ABI dumps: "false"
14107 # new ABI dumps: "0"
14108 $Value_Old = "0";
14109 }
14110 }
14111 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014112 if(not checkDump(1, "2.18")
14113 and checkDump(2, "2.18"))
14114 { # support for old ABI dumps
14115 if(not defined $Value_Old
14116 and substr($Value_New, 0, 2) eq "_Z") {
14117 $Value_Old = $Value_New;
14118 }
14119 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014120 if(defined $Value_Old)
14121 {
14122 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14123 if(defined $Value_New)
14124 {
14125 $Value_New = showVal($Value_New, $PType2_Id, 2);
14126 if($Value_Old ne $Value_New)
14127 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014128 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014129 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014130 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014131 "Old_Value"=>$Value_Old,
14132 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014133 }
14134 }
14135 else
14136 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014137 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014138 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014139 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014140 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014141 }
14142 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143 elsif(defined $Value_New)
14144 {
14145 $Value_New = showVal($Value_New, $PType2_Id, 2);
14146 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14147 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014148 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149 "New_Value"=>$Value_New );
14150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014151 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014152
14153 if($ChkRnmd)
14154 {
14155 if($PName1 and $PName2 and $PName1 ne $PName2
14156 and $PType1_Id!=-1 and $PType2_Id!=-1
14157 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14158 { # except unnamed "..." value list (Id=-1)
14159 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14160 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014161 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014162 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14163 "Old_Value"=>$PName1,
14164 "New_Value"=>$PName2,
14165 "New_Signature"=>get_Signature($Symbol, 2) );
14166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014167 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014168
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014169 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014170 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014172 foreach my $SubProblemType (keys(%SubProblems))
14173 { # add new problems, remove false alarms
14174 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14175 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014176
14177 # quals
14178 if($SubProblemType eq "Parameter_Type"
14179 or $SubProblemType eq "Parameter_Type_And_Size"
14180 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014181 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014182 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014183 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014184 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014185 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014186 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014187 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14188 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14189 }
14190 }
14191 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14192 {
14193 if(removedQual($Old_Value, $New_Value, "volatile")) {
14194 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014195 }
14196 }
14197 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14198 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14199 { # int to "int const"
14200 delete($SubProblems{$SubProblemType});
14201 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014202 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014203 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14204 { # "int const" to int
14205 delete($SubProblems{$SubProblemType});
14206 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014207 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14208 { # "const" to non-"const"
14209 if($RR==2) {
14210 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14211 }
14212 else {
14213 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14214 }
14215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014216 }
14217 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014218
14219 if($Level eq "Source")
14220 {
14221 foreach my $SubProblemType (keys(%SubProblems))
14222 {
14223 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14224 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14225
14226 if($SubProblemType eq "Parameter_Type")
14227 {
14228 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14229 delete($SubProblems{$SubProblemType});
14230 }
14231 }
14232 }
14233 }
14234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014235 foreach my $SubProblemType (keys(%SubProblems))
14236 { # modify/register problems
14237 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14238 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014239 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14240 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014242 my $NewProblemType = $SubProblemType;
14243 if($Old_Value eq "..." and $New_Value ne "...")
14244 { # change from "..." to "int"
14245 if($ParamPos1==0)
14246 { # ISO C requires a named argument before "..."
14247 next;
14248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014249 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014250 }
14251 elsif($New_Value eq "..." and $Old_Value ne "...")
14252 { # change from "int" to "..."
14253 if($ParamPos2==0)
14254 { # ISO C requires a named argument before "..."
14255 next;
14256 }
14257 $NewProblemType = "Parameter_Became_VaList";
14258 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014259 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014260 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 {
14262 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014263 if($Arch1 eq "unknown"
14264 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014265 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014266 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 ($Arch1, $Arch2) = ("unknown", "unknown");
14268 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014269 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014270 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014271 { # real
14272 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14273 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14274 }
14275 else
14276 { # model
14277 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14278 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14279 }
14280 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014281 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014282 if($Conv1{"Method"} eq "stack")
14283 {
14284 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14285 $NewProblemType = "Parameter_Type_And_Stack";
14286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014287 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014288 elsif($Conv1{"Method"} eq "reg")
14289 {
14290 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14291 $NewProblemType = "Parameter_Type_And_Register";
14292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014293 }
14294 }
14295 else
14296 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014297 if($Conv1{"Method"} eq "stack") {
14298 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014299 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014300 elsif($Conv1{"Method"} eq "register") {
14301 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 }
14303 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014304 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14305 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014307 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014308 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014309 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014310 "New_Signature"=>get_Signature($Symbol, 2) );
14311 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014312 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014313
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014315
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014316 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014317 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14318 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014319 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014320 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014321 {
14322 my $NewProblemType = $SubProblemType;
14323 if($SubProblemType eq "DataType_Size")
14324 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014325 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014326 { # stack has been affected
14327 $NewProblemType = "DataType_Size_And_Stack";
14328 }
14329 }
14330 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014331 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014332 }
14333 }
14334}
14335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336sub find_ParamPair_Pos_byName($$$)
14337{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014338 my ($Name, $Symbol, $LibVersion) = @_;
14339 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014340 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014341 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14342 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014343 {
14344 return $ParamPos;
14345 }
14346 }
14347 return "lost";
14348}
14349
14350sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14351{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014352 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014353 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014354 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014355 {
14356 next if($Order eq "backward" and $ParamPos>$MediumPos);
14357 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014358 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14359 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014360 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014361 push(@Positions, $ParamPos);
14362 }
14363 }
14364 return @Positions;
14365}
14366
14367sub getTypeIdByName($$)
14368{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014369 my ($TypeName, $LibVersion) = @_;
14370 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014371}
14372
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014373sub diffTypes($$$)
14374{
14375 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14376 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14377 }
14378 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14379 { # skip recursive declarations
14380 return 0;
14381 }
14382
14383 pushType($_[0], $_[1], \@RecurTypes_Diff);
14384 my $Diff = diffTypes_I(@_);
14385 pop(@RecurTypes_Diff);
14386
14387 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14388}
14389
14390sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014391{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014392 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014393
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014394 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14395 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014397 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14398 { # equal types
14399 return 0;
14400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014401 if($Type1_Pure{"Name"} eq "void")
14402 { # from void* to something
14403 return 0;
14404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014405 if($Type1_Pure{"Name"}=~/\*/
14406 or $Type2_Pure{"Name"}=~/\*/)
14407 { # compared in detectTypeChange()
14408 return 0;
14409 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 my %FloatType = map {$_=>1} (
14412 "float",
14413 "double",
14414 "long double"
14415 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014416
14417 my $T1 = $Type1_Pure{"Type"};
14418 my $T2 = $Type2_Pure{"Type"};
14419
14420 if($T1 eq "Struct"
14421 and $T2 eq "Class")
14422 { # compare as data structures
14423 $T2 = "Struct";
14424 }
14425
14426 if($T1 eq "Class"
14427 and $T2 eq "Struct")
14428 { # compare as data structures
14429 $T1 = "Struct";
14430 }
14431
14432 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014433 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014434 if($T1 eq "Intrinsic"
14435 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436 { # "int" to "enum"
14437 return 0;
14438 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014439 elsif($T2 eq "Intrinsic"
14440 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014441 { # "enum" to "int"
14442 return 0;
14443 }
14444 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014445 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014446 # ...
14447 return 1;
14448 }
14449 }
14450 else
14451 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014452 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014453 {
14454 if($FloatType{$Type1_Pure{"Name"}}
14455 or $FloatType{$Type2_Pure{"Name"}})
14456 { # "float" to "double"
14457 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014458 if($Level eq "Source")
14459 { # Safe
14460 return 0;
14461 }
14462 else {
14463 return 1;
14464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465 }
14466 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014467 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 {
14469 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14470 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014471 if(not @Membs1
14472 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014473 { # private
14474 return 0;
14475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 if($#Membs1!=$#Membs2)
14477 { # different number of elements
14478 return 1;
14479 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014480 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014481 {
14482 foreach my $Pos (@Membs1)
14483 { # compare elements by name and value
14484 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14485 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14486 { # different names
14487 return 1;
14488 }
14489 }
14490 }
14491 else
14492 {
14493 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014494 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014495 if($Level eq "Source")
14496 {
14497 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14498 { # different names
14499 return 1;
14500 }
14501 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014502
14503 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14504 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14505
14506 if($MT1{"Name"} ne $MT2{"Name"}
14507 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14508 {
14509 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14510 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14511
14512 if($PL1 ne $PL2)
14513 { # different pointer level
14514 return 1;
14515 }
14516
14517 # compare base types
14518 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14519 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14520
14521 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14522 { # different types
14523 return 1;
14524 }
14525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
14527 }
14528 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014529 else
14530 {
14531 # TODO: arrays, etc.
14532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 }
14534 return 0;
14535}
14536
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014537sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014539 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014540 if(not $Type1_Id or not $Type2_Id) {
14541 return ();
14542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014543 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014544 my %Type1 = get_Type($Type1_Id, 1);
14545 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014546 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14547 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14548 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14549 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 +040014550
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014551 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14552 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014553 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14554 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14555 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14556 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14557 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14558 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14559 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014560 if($Type1{"Name"} eq $Type2{"Name"})
14561 {
14562 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14563 { # will be reported in mergeTypes() as typedef problem
14564 return ();
14565 }
14566 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14567 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14568 if(%Typedef_1 and %Typedef_2)
14569 {
14570 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14571 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14572 { # const Typedef
14573 return ();
14574 }
14575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576 }
14577 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14578 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014579 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014580 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14581 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014582 {
14583 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14584 "Old_Value"=>$Type1_Base{"Name"},
14585 "New_Value"=>$Type2_Base{"Name"},
14586 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014587 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 }
14589 else
14590 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014591 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014592 { # format change
14593 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14594 "Old_Value"=>$Type1_Base{"Name"},
14595 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014596 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014597 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598 }
14599 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14600 {
14601 %{$LocalProblems{$Prefix."_BaseType"}}=(
14602 "Old_Value"=>$Type1_Base{"Name"},
14603 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014604 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014605 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 }
14607 }
14608 }
14609 }
14610 elsif($Type1{"Name"} ne $Type2{"Name"})
14611 { # type change
14612 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14613 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014614 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014615 and $Type1_Pure{"Name"} eq "void")
14616 {
14617 %{$LocalProblems{"Return_Type_From_Void"}}=(
14618 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014619 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 elsif($Prefix eq "Return"
14622 and $Type2_Pure{"Name"} eq "void")
14623 {
14624 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14625 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014626 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 else
14629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014630 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014631 and $Type1{"Size"} and $Type2{"Size"}
14632 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014633 {
14634 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14635 "Old_Value"=>$Type1{"Name"},
14636 "New_Value"=>$Type2{"Name"},
14637 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014638 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 }
14640 else
14641 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014642 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014643 { # format change
14644 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14645 "Old_Value"=>$Type1{"Name"},
14646 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014647 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014648 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 }
14650 elsif(tNameLock($Type1_Id, $Type2_Id))
14651 { # FIXME: correct this condition
14652 %{$LocalProblems{$Prefix."_Type"}}=(
14653 "Old_Value"=>$Type1{"Name"},
14654 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014655 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014656 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014657 }
14658 }
14659 }
14660 }
14661 }
14662 if($Type1_PLevel!=$Type2_PLevel)
14663 {
14664 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14665 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14666 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014667 if($Level eq "Source")
14668 {
14669 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014670 "Old_Value"=>$Type1_PLevel,
14671 "New_Value"=>$Type2_PLevel);
14672 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014673 else
14674 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014675 if($Type2_PLevel>$Type1_PLevel)
14676 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014677 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14678 "Old_Value"=>$Type1_PLevel,
14679 "New_Value"=>$Type2_PLevel);
14680 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014681 else
14682 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014683 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14684 "Old_Value"=>$Type1_PLevel,
14685 "New_Value"=>$Type2_PLevel);
14686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014687 }
14688 }
14689 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014690 if($Type1_Pure{"Type"} eq "Array"
14691 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 { # base_type[N] -> base_type[N]
14693 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014694 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014695 foreach my $SubProblemType (keys(%SubProblems))
14696 {
14697 $SubProblemType=~s/_Type/_BaseType/g;
14698 next if(defined $LocalProblems{$SubProblemType});
14699 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14700 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14701 }
14702 }
14703 }
14704 return %LocalProblems;
14705}
14706
14707sub tNameLock($$)
14708{
14709 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014710 my $Changed = 0;
14711 if(differentDumps("G"))
14712 { # different GCC versions
14713 $Changed = 1;
14714 }
14715 elsif(differentDumps("V"))
14716 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014717 if(not checkDump(1, "2.20")
14718 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014719 { # latest names update
14720 # 2.6: added restrict qualifier
14721 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014722 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014723 $Changed = 1;
14724 }
14725 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014726
14727 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14728 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14729
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014730 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14731 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14732
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014733 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014734 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014735 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014736 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014737 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014739 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014740 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014741 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014742 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014743 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14744 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14745 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014746 { # equal base types
14747 return 0;
14748 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014749
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014750 if(not checkDump(1, "2.13")
14751 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014752 { # broken array names in ABI dumps < 2.13
14753 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014754 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014755 return 0;
14756 }
14757 }
14758
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014759 if(not checkDump(1, "2.6")
14760 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014761 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014762 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014763 and $TN2=~/\brestrict\b/) {
14764 return 0;
14765 }
14766 }
14767
14768 if(not checkDump(1, "2.20")
14769 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014770 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014771 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14772 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014773 return 0;
14774 }
14775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014776 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014777 else
14778 {
14779 # typedef struct {...} type_t
14780 # typedef struct type_t {...} type_t
14781 if(index($TN1, " ".$TN2)!=-1)
14782 {
14783 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14784 return 0;
14785 }
14786 }
14787 if(index($TN2, " ".$TN1)!=-1)
14788 {
14789 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14790 return 0;
14791 }
14792 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014793
14794 if($TT1 eq "FuncPtr"
14795 and $TT2 eq "FuncPtr")
14796 {
14797 my $TN1_C = $TN1;
14798 my $TN2_C = $TN2;
14799
14800 $TN1_C=~s/\b(struct|union) //g;
14801 $TN2_C=~s/\b(struct|union) //g;
14802
14803 if($TN1_C eq $TN2_C) {
14804 return 0;
14805 }
14806 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014807 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014808
14809 my ($N1, $N2) = ($TN1, $TN2);
14810 $N1=~s/\b(struct|union) //g;
14811 $N2=~s/\b(struct|union) //g;
14812
14813 if($N1 eq $N2)
14814 { # QList<struct QUrl> and QList<QUrl>
14815 return 0;
14816 }
14817
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014818 return 1;
14819}
14820
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014821sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014823 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014824 if(defined $Cache{"differentDumps"}{$Check}) {
14825 return $Cache{"differentDumps"}{$Check};
14826 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014827 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014828 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014829 if($Check eq "G")
14830 {
14831 if(getGccVersion(1) ne getGccVersion(2))
14832 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014833 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014834 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014835 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014836 if($Check eq "V")
14837 {
14838 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14839 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14840 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014841 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014844 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014845 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846}
14847
14848sub formatVersion($$)
14849{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014850 my ($V, $Digits) = @_;
14851 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 return join(".", splice(@Elems, 0, $Digits));
14853}
14854
14855sub htmlSpecChars($)
14856{
14857 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014858 if(not $Str) {
14859 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14862 $Str=~s/</&lt;/g;
14863 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14864 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014865 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14866 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014867 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014868 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014869 $Str=~s/\n/<br\/>/g;
14870 $Str=~s/\"/&quot;/g;
14871 $Str=~s/\'/&#39;/g;
14872 return $Str;
14873}
14874
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014875sub xmlSpecChars($)
14876{
14877 my $Str = $_[0];
14878 if(not $Str) {
14879 return $Str;
14880 }
14881
14882 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14883 $Str=~s/</&lt;/g;
14884 $Str=~s/>/&gt;/g;
14885
14886 $Str=~s/\"/&quot;/g;
14887 $Str=~s/\'/&#39;/g;
14888
14889 return $Str;
14890}
14891
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014892sub xmlSpecChars_R($)
14893{
14894 my $Str = $_[0];
14895 if(not $Str) {
14896 return $Str;
14897 }
14898
14899 $Str=~s/&amp;/&/g;
14900 $Str=~s/&lt;/</g;
14901 $Str=~s/&gt;/>/g;
14902
14903 $Str=~s/&quot;/"/g;
14904 $Str=~s/&#39;/'/g;
14905
14906 return $Str;
14907}
14908
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014909sub black_name($)
14910{
14911 my $Name = $_[0];
14912 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14913}
14914
14915sub highLight_Signature($)
14916{
14917 my $Signature = $_[0];
14918 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14919}
14920
14921sub highLight_Signature_Italic_Color($)
14922{
14923 my $Signature = $_[0];
14924 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14925}
14926
14927sub separate_symbol($)
14928{
14929 my $Symbol = $_[0];
14930 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14931 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14932 ($Name, $Spec, $Ver) = ($1, $2, $3);
14933 }
14934 return ($Name, $Spec, $Ver);
14935}
14936
14937sub cut_f_attrs($)
14938{
14939 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14940 return $2;
14941 }
14942 return "";
14943}
14944
14945sub highLight_Signature_PPos_Italic($$$$$)
14946{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014947 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14948 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14950 my $Return = "";
14951 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14952 $Return = $2;
14953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014954 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014956 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014957 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014958 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014959 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014960 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014961 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
14963 return $Signature;
14964 }
14965 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14966 $Begin.=" " if($Begin!~/ \Z/);
14967 $End = cut_f_attrs($Signature);
14968 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014969 my ($Short, $Params) = split_Signature($Signature);
14970 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014971 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014972 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014973 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014974 $Part=~s/\A\s+|\s+\Z//g;
14975 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14976 if($Part=~/\([\*]+(\w+)\)/i) {
14977 $ParamName = $1;#func-ptr
14978 }
14979 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14980 $ParamName = $1;
14981 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014982 if(not $ParamName)
14983 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 push(@Parts, $Part_Styled);
14985 next;
14986 }
14987 if($ItalicParams and not $TName_Tid{1}{$Part}
14988 and not $TName_Tid{2}{$Part})
14989 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014990 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014991 if($Param_Pos ne ""
14992 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014993 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014994 }
14995 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014996 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014998 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014999 }
15000 $Part_Styled=~s/,(\w)/, $1/g;
15001 push(@Parts, $Part_Styled);
15002 }
15003 if(@Parts)
15004 {
15005 foreach my $Num (0 .. $#Parts)
15006 {
15007 if($Num==$#Parts)
15008 { # add ")" to the last parameter
15009 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15010 }
15011 elsif(length($Parts[$Num])<=45) {
15012 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15013 }
15014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015015 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015016 }
15017 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015018 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015019 }
15020 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015021 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015023 $Signature=~s!\[\]![&#160;]!g;
15024 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015025 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15026 if($SymbolVersion) {
15027 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15028 }
15029 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015030}
15031
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015032sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015033{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015034 my $Signature = $_[0];
15035 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15036 {
15037 $Signature=~s/\A\Q$ShortName\E\(//g;
15038 cut_f_attrs($Signature);
15039 $Signature=~s/\)\Z//;
15040 return ($ShortName, $Signature);
15041 }
15042
15043 # error
15044 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015045}
15046
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015047sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015048{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015049 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015050 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015051 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15052 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015053 foreach my $Pos (0 .. length($Params) - 1)
15054 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015055 my $S = substr($Params, $Pos, 1);
15056 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015057 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015058 }
15059 if($S eq "," and
15060 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015061 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015062 if($Comma)
15063 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015064 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015065 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015066 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015067 }
15068 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015069 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070 }
15071 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015072 if(not $Sp)
15073 { # remove spaces
15074 foreach (@Parts)
15075 {
15076 s/\A //g;
15077 s/ \Z//g;
15078 }
15079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015080 return @Parts;
15081}
15082
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015083sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015084{
15085 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015086 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015087 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015088 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15089 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090 $Center+=length($1);
15091 }
15092 foreach my $Pos (0 .. length($Sign)-1)
15093 {
15094 my $S = substr($Sign, $Pos, 1);
15095 if($S eq $Target)
15096 {
15097 if($B{"("}==$B{")"}
15098 and $B{"<"}==$B{">"}) {
15099 return $Center;
15100 }
15101 }
15102 if(defined $B{$S}) {
15103 $B{$S}+=1;
15104 }
15105 $Center+=1;
15106 }
15107 return 0;
15108}
15109
15110sub appendFile($$)
15111{
15112 my ($Path, $Content) = @_;
15113 return if(not $Path);
15114 if(my $Dir = get_dirname($Path)) {
15115 mkpath($Dir);
15116 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015117 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015118 print FILE $Content;
15119 close(FILE);
15120}
15121
15122sub writeFile($$)
15123{
15124 my ($Path, $Content) = @_;
15125 return if(not $Path);
15126 if(my $Dir = get_dirname($Path)) {
15127 mkpath($Dir);
15128 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015129 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 print FILE $Content;
15131 close(FILE);
15132}
15133
15134sub readFile($)
15135{
15136 my $Path = $_[0];
15137 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015138 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015139 local $/ = undef;
15140 my $Content = <FILE>;
15141 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015142 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015143 $Content=~s/\r/\n/g;
15144 }
15145 return $Content;
15146}
15147
15148sub get_filename($)
15149{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015150 if(defined $Cache{"get_filename"}{$_[0]}) {
15151 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015152 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015153 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15154 return ($Cache{"get_filename"}{$_[0]}=$1);
15155 }
15156 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157}
15158
15159sub get_dirname($)
15160{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015161 if(defined $Cache{"get_dirname"}{$_[0]}) {
15162 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015164 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15165 return ($Cache{"get_dirname"}{$_[0]}=$1);
15166 }
15167 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015168}
15169
15170sub separate_path($) {
15171 return (get_dirname($_[0]), get_filename($_[0]));
15172}
15173
15174sub esc($)
15175{
15176 my $Str = $_[0];
15177 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15178 return $Str;
15179}
15180
15181sub readLineNum($$)
15182{
15183 my ($Path, $Num) = @_;
15184 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015185 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015186 foreach (1 ... $Num) {
15187 <FILE>;
15188 }
15189 my $Line = <FILE>;
15190 close(FILE);
15191 return $Line;
15192}
15193
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015194sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015196 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 return () if(not $Path or not -f $Path);
15198 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015199 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15200 {
15201 foreach my $AttrVal (split(/;/, $1))
15202 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203 if($AttrVal=~/(.+):(.+)/)
15204 {
15205 my ($Name, $Value) = ($1, $2);
15206 $Attributes{$Name} = $Value;
15207 }
15208 }
15209 }
15210 return \%Attributes;
15211}
15212
15213sub is_abs($) {
15214 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15215}
15216
15217sub get_abs_path($)
15218{ # abs_path() should NOT be called for absolute inputs
15219 # because it can change them
15220 my $Path = $_[0];
15221 if(not is_abs($Path)) {
15222 $Path = abs_path($Path);
15223 }
15224 return $Path;
15225}
15226
15227sub get_OSgroup()
15228{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015229 my $N = $Config{"osname"};
15230 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 return "macos";
15232 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015233 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 return "bsd";
15235 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015236 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 return "beos";
15238 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015239 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 return "symbian";
15241 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015242 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 return "windows";
15244 }
15245 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015246 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015247 }
15248}
15249
15250sub getGccVersion($)
15251{
15252 my $LibVersion = $_[0];
15253 if($GCC_VERSION{$LibVersion})
15254 { # dump version
15255 return $GCC_VERSION{$LibVersion};
15256 }
15257 elsif($UsedDump{$LibVersion}{"V"})
15258 { # old-version dumps
15259 return "unknown";
15260 }
15261 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15262 if(not $GccVersion) {
15263 return "unknown";
15264 }
15265 return $GccVersion;
15266}
15267
15268sub showArch($)
15269{
15270 my $Arch = $_[0];
15271 if($Arch eq "arm"
15272 or $Arch eq "mips") {
15273 return uc($Arch);
15274 }
15275 return $Arch;
15276}
15277
15278sub getArch($)
15279{
15280 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015281
15282 if($TargetArch) {
15283 return $TargetArch;
15284 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015285 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015286 { # dump version
15287 return $CPU_ARCH{$LibVersion};
15288 }
15289 elsif($UsedDump{$LibVersion}{"V"})
15290 { # old-version dumps
15291 return "unknown";
15292 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015293
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015294 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015295}
15296
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015297sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015299 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015300
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015302 if(getArch(1) ne getArch(2)
15303 or getArch(1) eq "unknown"
15304 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015305 { # don't show architecture in the header
15306 $ArchInfo="";
15307 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015308 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015309 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015310 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015311 }
15312 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015313 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015314 }
15315 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015316 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015317 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015318
15319 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15320 {
15321 my $M1 = $UsedDump{1}{"M"};
15322 my $M2 = $UsedDump{2}{"M"};
15323
15324 if($M1 eq $M2)
15325 {
15326 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15327 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15328 }
15329 else
15330 {
15331 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15332 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15333 }
15334 }
15335 else
15336 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015337 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015338 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15339 }
15340
15341 $Title .= $ArchInfo;
15342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015343 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015344 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015345 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015346 $Title = "<h1>".$Title."</h1>\n";
15347 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348}
15349
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015350sub get_CheckedHeaders($)
15351{
15352 my $LibVersion = $_[0];
15353
15354 my @Headers = ();
15355
15356 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15357 {
15358 my $File = get_filename($Path);
15359 if(not is_target_header($File, $LibVersion)) {
15360 next;
15361 }
15362
15363 if(skipHeader($File, $LibVersion)) {
15364 next;
15365 }
15366
15367 push(@Headers, $Path);
15368 }
15369
15370 return @Headers;
15371}
15372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015373sub get_SourceInfo()
15374{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015375 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015376
15377 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015378 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015379 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15380 $CheckedHeaders .= "<div class='h_list'>\n";
15381 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 +040015382 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015383 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15384 my $Name = get_filename($Identity);
15385 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15386 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015387 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015388 $CheckedHeaders .= "</div>\n";
15389 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015390 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015391
15392 if(my @Sources = keys(%{$Registered_Sources{1}}))
15393 {
15394 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15395 $CheckedSources .= "<div class='h_list'>\n";
15396 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15397 {
15398 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15399 my $Name = get_filename($Identity);
15400 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15401 $CheckedSources .= $Name.$Comment."<br/>\n";
15402 }
15403 $CheckedSources .= "</div>\n";
15404 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15405 }
15406
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015407 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015409 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015410 $CheckedLibs .= "<div class='lib_list'>\n";
15411 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15412 {
15413 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15414 $CheckedLibs .= $Library."<br/>\n";
15415 }
15416 $CheckedLibs .= "</div>\n";
15417 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015419
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015420 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15421}
15422
15423sub get_ObjTitle()
15424{
15425 if(defined $UsedDump{1}{"DWARF"}) {
15426 return "Objects";
15427 }
15428 else {
15429 return ucfirst($SLIB_TYPE)." Libraries";
15430 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015431}
15432
15433sub get_TypeProblems_Count($$$)
15434{
15435 my ($TypeChanges, $TargetPriority, $Level) = @_;
15436 my $Type_Problems_Count = 0;
15437 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15438 {
15439 my %Kinds_Target = ();
15440 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15441 {
15442 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15443 {
15444 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015445 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15446 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015447 if($Kinds_Target{$Kind}{$Target}) {
15448 next;
15449 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015450
15451 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15452 {
15453 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15454 { # select a problem with the highest priority
15455 next;
15456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 }
15458 $Kinds_Target{$Kind}{$Target} = 1;
15459 $Type_Problems_Count += 1;
15460 }
15461 }
15462 }
15463 return $Type_Problems_Count;
15464}
15465
15466sub get_Summary($)
15467{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015468 my $Level = $_[0];
15469 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015470 $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 +040015471 %{$RESULT{$Level}} = (
15472 "Problems"=>0,
15473 "Warnings"=>0,
15474 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015476 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015478 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015479 {
15480 if(not defined $CompatRules{$Level}{$Kind})
15481 { # unknown rule
15482 if(not $UnknownRules{$Level}{$Kind})
15483 { # only one warning
15484 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15485 $UnknownRules{$Level}{$Kind}=1;
15486 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015487 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015488 }
15489 }
15490 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015491 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15492 {
15493 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15494 {
15495 if(not defined $CompatRules{$Level}{$Kind})
15496 { # unknown rule
15497 if(not $UnknownRules{$Level}{$Kind})
15498 { # only one warning
15499 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15500 $UnknownRules{$Level}{$Kind}=1;
15501 }
15502 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15503 }
15504 }
15505 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015506 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015507 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015508 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015509 {
15510 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15511 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015512 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015514 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015515 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 $Added += 1;
15517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015518 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015519 {
15520 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015521 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015522 }
15523 else
15524 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015525 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015526 $I_Other += 1;
15527 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015528 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 $I_Problems_High += 1;
15530 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015531 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532 $I_Problems_Medium += 1;
15533 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015534 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 $I_Problems_Low += 1;
15536 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015537 if(($Severity ne "Low" or $StrictCompat)
15538 and $Severity ne "Safe") {
15539 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540 }
15541 }
15542 }
15543 }
15544 }
15545 }
15546 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015547 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015548 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015549 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015550 {
15551 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15552 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015553 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015555 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15556 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015557 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015558 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15559
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015560 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 { # select a problem with the highest priority
15562 next;
15563 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015564
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015565 if(($Severity ne "Low" or $StrictCompat)
15566 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015567 {
15568 if(defined $TotalAffected{$Level}{$Interface})
15569 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015570 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15571 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015572 }
15573 }
15574 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015575 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015577 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015578
15579 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15580
15581 if($MaxSeverity)
15582 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015583 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15584 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015585 }
15586 }
15587 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015588 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 }
15591 }
15592 }
15593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15596 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15597 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15598 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015599
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015600 %TypeChanges = (); # free memory
15601
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015602 # changed and removed public symbols
15603 my $SCount = keys(%{$CheckedSymbols{$Level}});
15604 if($ExtendedCheck)
15605 { # don't count external_func_0 for constants
15606 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015607 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015608 if($SCount)
15609 {
15610 my %Weight = (
15611 "High" => 100,
15612 "Medium" => 50,
15613 "Low" => 25
15614 );
15615 foreach (keys(%{$TotalAffected{$Level}})) {
15616 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015617 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015618 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015620 else {
15621 $RESULT{$Level}{"Affected"} = 0;
15622 }
15623
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015624 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15625 if($RESULT{$Level}{"Affected"}>=100) {
15626 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 }
15628
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015629 $RESULT{$Level}{"Problems"} += $Removed;
15630 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015631 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015632 if($StrictCompat) {
15633 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15634 }
15635 else {
15636 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015638
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015639 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015640 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015641 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015642 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015643 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015644 if($Severity eq "Safe")
15645 {
15646 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015647 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015648 elsif($Severity eq "Low")
15649 {
15650 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015652 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015653 }
15654
15655 if($C_Problems_Low)
15656 {
15657 if($StrictCompat) {
15658 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15659 }
15660 else {
15661 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015662 }
15663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015664 if($RESULT{$Level}{"Problems"}
15665 and $RESULT{$Level}{"Affected"}) {
15666 $RESULT{$Level}{"Verdict"} = "incompatible";
15667 }
15668 else {
15669 $RESULT{$Level}{"Verdict"} = "compatible";
15670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015671
15672 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15673 if(not $TotalTypes)
15674 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 $TotalTypes = keys(%{$TName_Tid{1}});
15676 }
15677
15678 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15679 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15680
15681 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15682
15683 if($ReportFormat eq "xml")
15684 { # XML
15685 # test info
15686 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15687 $TestInfo .= " <version1>\n";
15688 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015689 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15691 $TestInfo .= " </version1>\n";
15692
15693 $TestInfo .= " <version2>\n";
15694 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015695 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15697 $TestInfo .= " </version2>\n";
15698 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15699
15700 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015701 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015702 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015703 $TestResults .= " <headers>\n";
15704 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15705 {
15706 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15707 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15708 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15709 }
15710 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015712
15713 if(my @Sources = keys(%{$Registered_Sources{1}}))
15714 {
15715 $TestResults .= " <sources>\n";
15716 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15717 {
15718 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15719 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15720 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15721 }
15722 $TestResults .= " </sources>\n";
15723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724
15725 $TestResults .= " <libs>\n";
15726 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15727 {
15728 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15729 $TestResults .= " <name>$Library</name>\n";
15730 }
15731 $TestResults .= " </libs>\n";
15732
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015733 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015734 $TestResults .= " <types>".$TotalTypes."</types>\n";
15735
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015736 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15737 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15739
15740 # problem summary
15741 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15742 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15743
15744 $Problem_Summary .= " <problems_with_types>\n";
15745 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15746 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15747 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15748 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15749 $Problem_Summary .= " </problems_with_types>\n";
15750
15751 $Problem_Summary .= " <problems_with_symbols>\n";
15752 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15753 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15754 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015755 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 $Problem_Summary .= " </problems_with_symbols>\n";
15757
15758 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015761
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015762 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15763
15764 return ($TestInfo.$TestResults.$Problem_Summary, "");
15765 }
15766 else
15767 { # HTML
15768 # test info
15769 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015770 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015771 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772
15773 my (@VInf1, @VInf2, $AddTestInfo) = ();
15774 if($Arch1 ne "unknown"
15775 and $Arch2 ne "unknown")
15776 { # CPU arch
15777 if($Arch1 eq $Arch2)
15778 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015779 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 }
15781 else
15782 { # go to the version number
15783 push(@VInf1, showArch($Arch1));
15784 push(@VInf2, showArch($Arch2));
15785 }
15786 }
15787 if($GccV1 ne "unknown"
15788 and $GccV2 ne "unknown"
15789 and $OStarget ne "windows")
15790 { # GCC version
15791 if($GccV1 eq $GccV2)
15792 { # go to the separate section
15793 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15794 }
15795 else
15796 { # go to the version number
15797 push(@VInf1, "gcc ".$GccV1);
15798 push(@VInf2, "gcc ".$GccV2);
15799 }
15800 }
15801 # show long version names with GCC version and CPU architecture name (if different)
15802 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15803 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15804 $TestInfo .= $AddTestInfo;
15805 #if($COMMON_LANGUAGE{1}) {
15806 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15807 #}
15808 if($ExtendedCheck) {
15809 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015811 if($JoinReport)
15812 {
15813 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015814 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015815 }
15816 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015817 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015818 }
15819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 $TestInfo .= "</table>\n";
15821
15822 # test results
15823 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015824 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015825
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015826 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015827 {
15828 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15829 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15830 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015831
15832 if(my @Sources = keys(%{$Registered_Sources{1}}))
15833 {
15834 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15835 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015837
15838 if(not $ExtendedCheck)
15839 {
15840 my $Libs_Link = "0";
15841 $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 +040015842 $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 +040015843 }
15844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015845 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015846
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015847 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015848 if($JoinReport) {
15849 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15850 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015851 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015852 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015853 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15854 }
15855 else {
15856 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15857 }
15858 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015859 $TestResults .= "</table>\n";
15860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 # problem summary
15863 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015864 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015865 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15866
15867 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 if($Added>0)
15869 {
15870 if($JoinReport) {
15871 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15872 }
15873 else {
15874 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15875 }
15876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015878 $Problem_Summary .= "<tr><th>Added Symbols</th><td>-</td><td".getStyle("I", "A", $Added).">$Added_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015879
15880 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 if($Removed>0)
15882 {
15883 if($JoinReport) {
15884 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15885 }
15886 else {
15887 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15888 }
15889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015891 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15892 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893
15894 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015895 $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 +040015896 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015897 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15898 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015899
15900 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015901 $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 +040015902 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015903 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "M", $T_Problems_Medium).">$TM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015904
15905 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015906 $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 +040015907 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015908 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "L", $T_Problems_Low).">$TL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909
15910 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015911 $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 +040015912 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015913 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15914 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915
15916 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015917 $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 +040015918 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015919 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("I", "M", $I_Problems_Medium).">$IM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015920
15921 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 $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 +040015923 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015924 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("I", "L", $I_Problems_Low).">$IL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015925
15926 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015927 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15928 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015931 $Problem_Summary .= "<tr><th>Problems with<br/>Constants</th><td>Low</td><td".getStyle("C", "L", $C_Problems_Low).">$ChangedConstants_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015934 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015935 {
15936 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015937 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "S", $T_Other).">$TS_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015939
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015940 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015941 {
15942 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015943 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015946 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015947 {
15948 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15949 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15950 }
15951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 $META_DATA .= "tool_version:$TOOL_VERSION";
15953 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015954 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15956 }
15957}
15958
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015959sub getStyle($$$)
15960{
15961 my ($Subj, $Act, $Num) = @_;
15962 my %Style = (
15963 "A"=>"new",
15964 "R"=>"failed",
15965 "S"=>"passed",
15966 "L"=>"warning",
15967 "M"=>"failed",
15968 "H"=>"failed"
15969 );
15970 if($Num>0) {
15971 return " class='".$Style{$Act}."'";
15972 }
15973 return "";
15974}
15975
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015976sub show_number($)
15977{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015980 my $Num = cut_off_number($_[0], 2, 0);
15981 if($Num eq "0")
15982 {
15983 foreach my $P (3 .. 7)
15984 {
15985 $Num = cut_off_number($_[0], $P, 1);
15986 if($Num ne "0") {
15987 last;
15988 }
15989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015990 }
15991 if($Num eq "0") {
15992 $Num = $_[0];
15993 }
15994 return $Num;
15995 }
15996 return $_[0];
15997}
15998
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015999sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016000{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016001 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016002 if($num!~/\./)
16003 {
16004 $num .= ".";
16005 foreach (1 .. $digs_to_cut-1) {
16006 $num .= "0";
16007 }
16008 }
16009 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16010 {
16011 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16012 $num .= "0";
16013 }
16014 }
16015 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16016 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16017 }
16018 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016019 if($z) {
16020 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022 return $num;
16023}
16024
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016025sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016026{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016027 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016028 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016029
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016030 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016031 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16032 {
16033 my $Header = $Constants{1}{$Constant}{"Header"};
16034 if(not $Header)
16035 { # added
16036 $Header = $Constants{2}{$Constant}{"Header"}
16037 }
16038
16039 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16040 {
16041 if(not defined $CompatRules{$Level}{$Kind}) {
16042 next;
16043 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016044 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016045 next;
16046 }
16047 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016050
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016051 if($ReportFormat eq "xml")
16052 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016053 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016054 {
16055 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016056 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016057 {
16058 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016059 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16060 {
16061 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16062 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16063 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016064
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016065 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16066 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16067 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016068 if($Overcome) {
16069 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16070 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016071 $CHANGED_CONSTANTS .= " </problem>\n";
16072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016073 $CHANGED_CONSTANTS .= " </constant>\n";
16074 }
16075 $CHANGED_CONSTANTS .= " </header>\n";
16076 }
16077 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16078 }
16079 else
16080 { # HTML
16081 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016082 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016083 {
16084 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016085 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016087 my $Report = "";
16088
16089 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16090 {
16091 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16092 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16093 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16094 $Number += 1;
16095 }
16096 if($Report)
16097 {
16098 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16099 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16100 $Report = insertIDs($Report);
16101 }
16102 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016103 }
16104 $CHANGED_CONSTANTS .= "<br/>\n";
16105 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016106 if($CHANGED_CONSTANTS)
16107 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016108 my $Title = "Problems with Constants, $TargetSeverity Severity";
16109 if($TargetSeverity eq "Safe")
16110 { # Safe Changes
16111 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016112 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016113 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a><h2>$Title ($Number)</h2><hr/>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016114 }
16115 }
16116 return $CHANGED_CONSTANTS;
16117}
16118
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016119sub getTitle($$$)
16120{
16121 my ($Header, $Library, $NameSpace) = @_;
16122 my $Title = "";
16123 if($Library and $Library!~/\.\w+\Z/) {
16124 $Library .= " (.$LIB_EXT)";
16125 }
16126 if($Header and $Library)
16127 {
16128 $Title .= "<span class='h_name'>$Header</span>";
16129 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16130 }
16131 elsif($Library) {
16132 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16133 }
16134 elsif($Header) {
16135 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16136 }
16137 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016138 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016139 }
16140 return $Title;
16141}
16142
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143sub get_Report_Added($)
16144{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016145 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016146 my $ADDED_INTERFACES = "";
16147 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016150 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016152 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016153 {
16154 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16155 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016156 if($Level eq "Source" and $ReportFormat eq "html")
16157 { # do not show library name in HTML report
16158 $DyLib = "";
16159 }
16160 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016161 }
16162 }
16163 }
16164 if($ReportFormat eq "xml")
16165 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016166 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167 {
16168 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016169 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 {
16171 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16174 }
16175 $ADDED_INTERFACES .= " </library>\n";
16176 }
16177 $ADDED_INTERFACES .= " </header>\n";
16178 }
16179 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16180 }
16181 else
16182 { # HTML
16183 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016186 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 my %NameSpaceSymbols = ();
16189 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016190 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016191 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016192 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016193 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16195 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016196 foreach my $Interface (@SortedInterfaces)
16197 {
16198 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199 my $Signature = get_Signature($Interface, 2);
16200 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016201 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016203 if($Interface=~/\A(_Z|\?)/)
16204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016205 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016206 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016207 }
16208 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016210 }
16211 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016212 else
16213 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016214 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216 }
16217 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016218 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016219 }
16220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016221 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016222 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 }
16225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 if($ADDED_INTERFACES)
16227 {
16228 my $Anchor = "<a name='Added'></a>";
16229 if($JoinReport) {
16230 $Anchor = "<a name='".$Level."_Added'></a>";
16231 }
16232 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016233 }
16234 }
16235 return $ADDED_INTERFACES;
16236}
16237
16238sub get_Report_Removed($)
16239{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016240 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016241 my $REMOVED_INTERFACES = "";
16242 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016243 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016244 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016245 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016249 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16250 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 if($Level eq "Source" and $ReportFormat eq "html")
16252 { # do not show library name in HTML report
16253 $DyLib = "";
16254 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016255 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 }
16257 }
16258 }
16259 if($ReportFormat eq "xml")
16260 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016261 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016262 {
16263 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016264 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 {
16266 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016267 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16268 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 }
16270 $REMOVED_INTERFACES .= " </library>\n";
16271 }
16272 $REMOVED_INTERFACES .= " </header>\n";
16273 }
16274 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16275 }
16276 else
16277 { # HTML
16278 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016279 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016281 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016283 my %NameSpaceSymbols = ();
16284 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016285 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016287 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016288 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016289 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16290 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016291 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292 {
16293 $Removed_Number += 1;
16294 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016295 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016296 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016297 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016298 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016299 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016302 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 }
16304 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016305 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 }
16307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016308 else
16309 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 }
16313 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016314 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 }
16316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 }
16318 }
16319 $REMOVED_INTERFACES .= "<br/>\n";
16320 }
16321 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016322 if($REMOVED_INTERFACES)
16323 {
16324 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16325 if($JoinReport) {
16326 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16327 }
16328 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 }
16330 }
16331 return $REMOVED_INTERFACES;
16332}
16333
16334sub getXmlParams($$)
16335{
16336 my ($Content, $Problem) = @_;
16337 return "" if(not $Content or not $Problem);
16338 my %XMLparams = ();
16339 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16340 {
16341 my $Macro = "\@".lc($Attr);
16342 if($Content=~/\Q$Macro\E/) {
16343 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16344 }
16345 }
16346 my @PString = ();
16347 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016348 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016349 }
16350 if(@PString) {
16351 return " ".join(" ", @PString);
16352 }
16353 else {
16354 return "";
16355 }
16356}
16357
16358sub addMarkup($)
16359{
16360 my $Content = $_[0];
16361 # auto-markup
16362 $Content=~s/\n[ ]*//; # spaces
16363 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16364 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016365 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16367 if($Content=~/\ANOTE:/)
16368 { # notes
16369 $Content=~s!(NOTE):!<b>$1</b>:!g;
16370 }
16371 else {
16372 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16373 }
16374 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16375 my @Keywords = (
16376 "void",
16377 "const",
16378 "static",
16379 "restrict",
16380 "volatile",
16381 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016382 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 );
16384 my $MKeys = join("|", @Keywords);
16385 foreach (@Keywords) {
16386 $MKeys .= "|non-".$_;
16387 }
16388 $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 +040016389
16390 # Markdown
16391 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16392 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016393 return $Content;
16394}
16395
16396sub applyMacroses($$$$)
16397{
16398 my ($Level, $Kind, $Content, $Problem) = @_;
16399 return "" if(not $Content or not $Problem);
16400 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16401 $Content = addMarkup($Content);
16402 # macros
16403 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16404 {
16405 my $Macro = "\@".lc($Attr);
16406 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016407 if(not defined $Value
16408 or $Value eq "") {
16409 next;
16410 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016411
16412 if(index($Content, $Macro)==-1) {
16413 next;
16414 }
16415
16416 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16417 and $Kind!~/_Type_/
16418 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016419 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016421 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 $Value = black_name($Value);
16423 }
16424 elsif($Value=~/\s/) {
16425 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16426 }
16427 elsif($Value=~/\A\d+\Z/
16428 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16429 { # bits to bytes
16430 if($Value % $BYTE_SIZE)
16431 { # bits
16432 if($Value==1) {
16433 $Value = "<b>".$Value."</b> bit";
16434 }
16435 else {
16436 $Value = "<b>".$Value."</b> bits";
16437 }
16438 }
16439 else
16440 { # bytes
16441 $Value /= $BYTE_SIZE;
16442 if($Value==1) {
16443 $Value = "<b>".$Value."</b> byte";
16444 }
16445 else {
16446 $Value = "<b>".$Value."</b> bytes";
16447 }
16448 }
16449 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016450 else
16451 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016452 $Value = "<b>".htmlSpecChars($Value)."</b>";
16453 }
16454 $Content=~s/\Q$Macro\E/$Value/g;
16455 }
16456
16457 if($Content=~/(\A|[^\@\w])\@\w/)
16458 {
16459 if(not $IncompleteRules{$Level}{$Kind})
16460 { # only one warning
16461 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16462 $IncompleteRules{$Level}{$Kind} = 1;
16463 }
16464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 return $Content;
16466}
16467
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016468sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016471 my $INTERFACE_PROBLEMS = "";
16472 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016473
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016474 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016475 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16477 if($SV and defined $CompatProblems{$Level}{$SN}) {
16478 next;
16479 }
16480 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 {
16482 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016485 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16486 my $DyLib = $Symbol_Library{1}{$Symbol};
16487 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016488 { # Symbol with Version
16489 $DyLib = $Symbol_Library{1}{$VSym};
16490 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016491 if(not $DyLib)
16492 { # const global data
16493 $DyLib = "";
16494 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 if($Level eq "Source" and $ReportFormat eq "html")
16496 { # do not show library name in HTML report
16497 $DyLib = "";
16498 }
16499 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16500 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016501 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016502 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16503 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016504 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016505 }
16506 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16508 {
16509 delete($SymbolChanges{$Symbol}{$Kind});
16510 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016512 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 }
16514 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016515 if(not keys(%{$SymbolChanges{$Symbol}})) {
16516 delete($SymbolChanges{$Symbol});
16517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016520 if($ReportFormat eq "xml")
16521 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016522 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 {
16524 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016525 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 {
16527 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016528 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16529 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 {
16531 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16532 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16533 {
16534 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16535 {
16536 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016537 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016539 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16540 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16541 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16542 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16543 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016544 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16545 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016547 $INTERFACE_PROBLEMS .= " </problem>\n";
16548 }
16549 }
16550 $INTERFACE_PROBLEMS .= " </symbol>\n";
16551 }
16552 $INTERFACE_PROBLEMS .= " </library>\n";
16553 }
16554 $INTERFACE_PROBLEMS .= " </header>\n";
16555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 }
16558 else
16559 { # HTML
16560 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016565 my (%NameSpaceSymbols, %NewSignature) = ();
16566 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016567 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016569 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016570 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016571 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016572 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 +040016573 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 my $Signature = get_Signature($Symbol, 1);
16576 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016578 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016583 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 }
16587 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16588 {
16589 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016590 $SYMBOL_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>".$Effect."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 $ProblemNum += 1;
16592 $ProblemsNum += 1;
16593 }
16594 }
16595 }
16596 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016599 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016600 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016601 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016602 }
16603 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016604 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016606 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16607 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16608 if($NewSignature{$Symbol})
16609 { # argument list changed to
16610 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span><br/><span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016612 if($Symbol=~/\A(_Z|\?)/) {
16613 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16614 }
16615 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16616 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016618 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016619 }
16620 }
16621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016622 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016623 }
16624 }
16625 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 if($INTERFACE_PROBLEMS)
16628 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016629 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16630 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16631 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 { # Safe Changes
16633 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016635 $INTERFACE_PROBLEMS = "<a name=\'".get_Anchor("Symbol", $Level, $TargetSeverity)."\'></a><a name=\'".get_Anchor("Interface", $Level, $TargetSeverity)."\'></a>\n<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016636 }
16637 }
16638 return $INTERFACE_PROBLEMS;
16639}
16640
16641sub get_Report_TypeProblems($$)
16642{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016644 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016645 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016646
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016649 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 {
16651 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16652 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016653 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016655 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016656 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016657 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016658
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016659 if($Severity eq "Safe"
16660 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 next;
16662 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016663
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016664 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16665 {
16666 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16667 { # select a problem with the highest priority
16668 next;
16669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016671
16672 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 }
16674 }
16675 }
16676 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016677
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 my %Kinds_Locations = ();
16679 foreach my $TypeName (keys(%TypeChanges))
16680 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016681 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16683 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016684 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016686 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016687 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 { # other priority
16689 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16690 next;
16691 }
16692 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16693 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016694 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016695 { # duplicate target
16696 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16697 next;
16698 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016699 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016700 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016701 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016702 }
16703 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16704 delete($TypeChanges{$TypeName}{$Kind});
16705 }
16706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016707 if(not keys(%{$TypeChanges{$TypeName}})) {
16708 delete($TypeChanges{$TypeName});
16709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016711
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016712 my @Symbols = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$CompatProblems{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 if($ReportFormat eq "xml")
16714 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016715 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016716 {
16717 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016720 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16722 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016723 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724 {
16725 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16726 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16727 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16728 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16729 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16730 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016731 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16732 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 $TYPE_PROBLEMS .= " </problem>\n";
16735 }
16736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016737 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016739 $TYPE_PROBLEMS .= showVTables($TypeName);
16740 }
16741 $TYPE_PROBLEMS .= " </type>\n";
16742 }
16743 $TYPE_PROBLEMS .= " </header>\n";
16744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016745 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 }
16747 else
16748 { # HTML
16749 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016750 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016751 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 my (%NameSpace_Type) = ();
16753 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016754 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016755 }
16756 foreach my $NameSpace (sort keys(%NameSpace_Type))
16757 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016758 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016759 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 +040016760 foreach my $TypeName (@SortedTypes)
16761 {
16762 my $ProblemNum = 1;
16763 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16766 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016767 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 {
16769 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16770 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16771 {
16772 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16773 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16774 $ProblemNum += 1;
16775 $ProblemsNum += 1;
16776 }
16777 }
16778 }
16779 $ProblemNum -= 1;
16780 if($TYPE_REPORT)
16781 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016782 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016783 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016784 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016785 $ShowVTables = showVTables($TypeName);
16786 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016787
16788 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016789 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16790 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16791 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16792 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016793 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016794 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795 }
16796 }
16797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016798 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 }
16800 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802 if($TYPE_PROBLEMS)
16803 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016804 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16805 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016806 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 { # Safe Changes
16808 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 }
16812 }
16813 return $TYPE_PROBLEMS;
16814}
16815
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016816sub show_Type($$$)
16817{
16818 my ($Name, $Html, $LibVersion) = @_;
16819 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16820 $TType = lc($TType);
16821 if($TType=~/struct|union|enum/) {
16822 $Name=~s/\A\Q$TType\E //g;
16823 }
16824 if($Html) {
16825 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16826 }
16827 else {
16828 $Name = $TType." ".$Name;
16829 }
16830 return $Name;
16831}
16832
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833sub get_Anchor($$$)
16834{
16835 my ($Kind, $Level, $Severity) = @_;
16836 if($JoinReport)
16837 {
16838 if($Severity eq "Safe") {
16839 return "Other_".$Level."_Changes_In_".$Kind."s";
16840 }
16841 else {
16842 return $Kind."_".$Level."_Problems_".$Severity;
16843 }
16844 }
16845 else
16846 {
16847 if($Severity eq "Safe") {
16848 return "Other_Changes_In_".$Kind."s";
16849 }
16850 else {
16851 return $Kind."_Problems_".$Severity;
16852 }
16853 }
16854}
16855
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856sub showVTables($)
16857{
16858 my $TypeName = $_[0];
16859 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016860 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016861 if(defined $Type1{"VTable"}
16862 and keys(%{$Type1{"VTable"}}))
16863 {
16864 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016865 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016866 if(defined $Type2{"VTable"}
16867 and keys(%{$Type2{"VTable"}}))
16868 {
16869 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16870 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016871 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16874 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 }
16876 my $VTABLES = "";
16877 if($ReportFormat eq "xml")
16878 { # XML
16879 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016880 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016881 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016882 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016883 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16884 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 $VTABLES .= " </entry>\n";
16886 }
16887 $VTABLES .= " </vtable>\n\n";
16888 }
16889 else
16890 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016892 $VTABLES .= "<tr><th>Offset</th>";
16893 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 {
16897 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016900 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016901 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016902 $Color1 = " class='failed'";
16903 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016904 }
16905 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016906 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 }
16908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016909 $VTABLES .= "<tr><th>".$Index."</th>\n";
16910 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16911 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 }
16913 $VTABLES .= "</table><br/>\n";
16914 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016915 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016916 }
16917 return $VTABLES;
16918 }
16919 }
16920 return "";
16921}
16922
16923sub simpleVEntry($)
16924{
16925 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016926 if(not defined $VEntry
16927 or $VEntry eq "") {
16928 return "";
16929 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016930
16931 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16933 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16934 if($VEntry=~/\A_ZThn.+\Z/) {
16935 $VEntry = "non-virtual thunk";
16936 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016937 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016938 # support for old GCC versions
16939 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16940 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16941 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016942 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16943 return $VEntry;
16944}
16945
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016946sub adjustParamPos($$$)
16947{
16948 my ($Pos, $Symbol, $LibVersion) = @_;
16949 if(defined $CompleteSignature{$LibVersion}{$Symbol})
16950 {
16951 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
16952 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
16953 {
16954 return $Pos-1;
16955 }
16956
16957 return $Pos;
16958 }
16959
16960 return undef;
16961}
16962
16963sub getParamPos($$$)
16964{
16965 my ($Name, $Symbol, $LibVersion) = @_;
16966
16967 if(defined $CompleteSignature{$LibVersion}{$Symbol}
16968 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
16969 {
16970 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16971 foreach (keys(%{$Info->{"Param"}}))
16972 {
16973 if($Info->{"Param"}{$_}{"name"} eq $Name)
16974 {
16975 return $_;
16976 }
16977 }
16978 }
16979
16980 return undef;
16981}
16982
16983sub getParamName($)
16984{
16985 my $Loc = $_[0];
16986 $Loc=~s/\->.*//g;
16987 return $Loc;
16988}
16989
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016990sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016992 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016993 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016994
16995 if(defined $AffectLimit)
16996 {
16997 $LIMIT = $AffectLimit;
16998 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016999
17000 my %SymSel = ();
17001 my %SymLocKind = ();
17002
17003 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017005 if(index($Symbol, "_Z")==0
17006 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 { # duplicated problems for C2 constructors, D2 and D0 destructors
17008 next;
17009 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017010
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017011 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017012 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017013 if(not defined $CompatProblems{$Level}{$Symbol}
17014 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17015 next;
17016 }
17017
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017018 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017019 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017020 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017021 next;
17022 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017023
17024 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17025 if($Level eq "Source")
17026 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017027 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017028 }
17029
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017030 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017031 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 { # duplicated problems for versioned symbols
17033 next;
17034 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017035
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017036 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017037 if($Type_Name ne $Target_TypeName) {
17038 next;
17039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017040
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017041 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 }
17043 }
17044 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017045
17046 foreach my $Symbol (sort keys(%SymLocKind))
17047 {
17048 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17049 {
17050 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17051 {
17052 $SymSel{$Symbol}{"Loc"} = $Loc;
17053 $SymSel{$Symbol}{"Kind"} = $Kind;
17054
17055 last LOOP;
17056 }
17057 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017058 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017060 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017061 my $Num = 0;
17062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017063 if($ReportFormat eq "xml")
17064 { # XML
17065 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017066
17067 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017068 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017069 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017070 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017071 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017072
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017073 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017074 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017075 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017076 $Target .= " param=\"$PName\"";
17077 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017079 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017080 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017082 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017083 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017085
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017086 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017087 $Target .= " field=\"$1\"";
17088 }
17089
17090 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017091 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017093
17094 if($Num>$LIMIT) {
17095 last LOOP;
17096 }
17097
17098 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017099 }
17100 $Affected .= " </affected>\n";
17101 }
17102 else
17103 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017104 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017106 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17107 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017108 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017109 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17110
17111 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17112 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17113
17114 if($Num>$LIMIT) {
17115 last;
17116 }
17117
17118 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017120
17121 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017122 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017124
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017125 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 if($Affected)
17127 {
17128 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017129 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 }
17131 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 return $Affected;
17134}
17135
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017136sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017138 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017139 if($L2=~/\A(retval|this)\b/
17140 and $L1!~/\A(retval|this)\b/)
17141 {
17142 if($L1!~/\-\>/) {
17143 return 1;
17144 }
17145 elsif($L2=~/\-\>/) {
17146 return 1;
17147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 }
17149 return 0;
17150}
17151
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017152sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017153{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017154 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017155
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017156 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017157
17158 my $Location_I = $Location;
17159 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17160
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017161 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 if($Kind eq "Overridden_Virtual_Method"
17164 or $Kind eq "Overridden_Virtual_Method_B") {
17165 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17166 }
17167 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17168 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017169 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17170
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017171 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17172 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017173 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17174 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 if($ClassName eq $Problem{"Type_Name"}) {
17177 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17178 }
17179 else {
17180 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17181 }
17182 }
17183 else
17184 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017185 my $TypeID = undef;
17186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 if($Location=~/retval/)
17188 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017189 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 push(@Sentence, "Field \'".$Location."\' in return value");
17191 }
17192 else {
17193 push(@Sentence, "Return value");
17194 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017195
17196 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197 }
17198 elsif($Location=~/this/)
17199 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017200 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17202 }
17203 else {
17204 push(@Sentence, "\'this\' pointer");
17205 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017206
17207 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 }
17209 else
17210 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017211
17212 my $PName = getParamName($Location);
17213 my $PPos = getParamPos($PName, $Symbol, 1);
17214
17215 if(index($Location, "->")!=-1) {
17216 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017217 }
17218 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017219 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017221 if($PName) {
17222 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017224
17225 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17226 }
17227
17228 if($Location!~/this/)
17229 {
17230 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017231 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017232 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017233 push(@Sentence, "(pointer)");
17234 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017235 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017236 push(@Sentence, "(reference)");
17237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017238 }
17239 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 if($Location eq "this") {
17242 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17243 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017244 else
17245 {
17246 my $Location_T = $Location;
17247 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17248
17249 my $TypeID_Problem = $TypeID;
17250 if($Location_T) {
17251 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17252 }
17253
17254 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17255 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17256 }
17257 else {
17258 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 }
17261 }
17262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017263 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017264 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 +040017265 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017266
17267 my $Sent = join(" ", @Sentence);
17268
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017269 $Sent=~s/->/./g;
17270
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017271 if($ReportFormat eq "xml")
17272 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017273 $Sent=~s/'//g;
17274 }
17275
17276 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277}
17278
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017279sub getFieldType($$$)
17280{
17281 my ($Location, $TypeId, $LibVersion) = @_;
17282
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017283 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017284
17285 foreach my $Name (@Fields)
17286 {
17287 my %Info = get_BaseType($TypeId, $LibVersion);
17288
17289 foreach my $Pos (keys(%{$Info{"Memb"}}))
17290 {
17291 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17292 {
17293 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17294 last;
17295 }
17296 }
17297 }
17298
17299 return $TypeId;
17300}
17301
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017302sub get_XmlSign($$)
17303{
17304 my ($Symbol, $LibVersion) = @_;
17305 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17306 my $Report = "";
17307 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17308 {
17309 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017310 my $Type = $Info->{"Param"}{$Pos}{"type"};
17311 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017312 foreach my $Typedef (keys(%ChangedTypedef))
17313 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017314 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17315 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 }
17318 $Report .= " <param pos=\"$Pos\">\n";
17319 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017320 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017321 $Report .= " </param>\n";
17322 }
17323 if(my $Return = $Info->{"Return"})
17324 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017325 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017327 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 $Report .= " </retval>\n";
17329 }
17330 return $Report;
17331}
17332
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017333sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017335 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017336 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017337 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017339 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17340 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017341 next;
17342 }
17343 $Report .= " <symbol name=\"$Symbol\">\n";
17344 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017345 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017346 {
17347 if(defined $CompleteSignature{1}{$Symbol}
17348 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17349 {
17350 $P1 = get_XmlSign($Symbol, 1);
17351 $S1 = get_Signature($Symbol, 1);
17352 }
17353 elsif($Symbol=~/\A(_Z|\?)/) {
17354 $S1 = $tr_name{$Symbol};
17355 }
17356 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017357 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017358 {
17359 if(defined $CompleteSignature{2}{$Symbol}
17360 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17361 {
17362 $P2 = get_XmlSign($Symbol, 2);
17363 $S2 = get_Signature($Symbol, 2);
17364 }
17365 elsif($Symbol=~/\A(_Z|\?)/) {
17366 $S2 = $tr_name{$Symbol};
17367 }
17368 }
17369 if($S1)
17370 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017371 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 $Report .= $P1;
17373 $Report .= " </old>\n";
17374 }
17375 if($S2 and $S2 ne $S1)
17376 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017377 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017378 $Report .= $P2;
17379 $Report .= " </new>\n";
17380 }
17381 $Report .= " </symbol>\n";
17382 }
17383 $Report .= "</symbols_info>\n";
17384 return $Report;
17385}
17386
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017387sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017389 my ($Level, $Report) = @_;
17390 if($ReportFormat eq "xml") {
17391 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017392 }
17393 if($StdOut)
17394 { # --stdout option
17395 print STDOUT $Report;
17396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017397 else
17398 {
17399 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017400 mkpath(get_dirname($RPath));
17401
17402 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17403 print REPORT $Report;
17404 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017405 }
17406}
17407
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017408sub getReport($)
17409{
17410 my $Level = $_[0];
17411 if($ReportFormat eq "xml")
17412 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017413 if($Level eq "Join")
17414 {
17415 my $Report = "<reports>\n";
17416 $Report .= getReport("Binary");
17417 $Report .= getReport("Source");
17418 $Report .= "</reports>\n";
17419 return $Report;
17420 }
17421 else
17422 {
17423 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17424 my ($Summary, $MetaData) = get_Summary($Level);
17425 $Report .= $Summary."\n";
17426 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17427 $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 +040017428
17429 # additional symbols info (if needed)
17430 # $Report .= get_Report_SymbolsInfo($Level);
17431
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017432 $Report .= "</report>\n";
17433 return $Report;
17434 }
17435 }
17436 else
17437 { # HTML
17438 my $CssStyles = readModule("Styles", "Report.css");
17439 my $JScripts = readModule("Scripts", "Sections.js");
17440 if($Level eq "Join")
17441 {
17442 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17443 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017444 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017445 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17446 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 +040017447 my ($BSummary, $BMetaData) = get_Summary("Binary");
17448 my ($SSummary, $SMetaData) = get_Summary("Source");
17449 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 +030017450 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017451 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017452 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17453 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017454 </div>";
17455 $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>";
17456 $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 +030017457 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017458 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017459 return $Report;
17460 }
17461 else
17462 {
17463 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017464 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17465 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17466 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 +040017467 if($Level eq "Binary")
17468 {
17469 if(getArch(1) eq getArch(2)
17470 and getArch(1) ne "unknown") {
17471 $Description .= " on ".showArch(getArch(1));
17472 }
17473 }
17474 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 +030017475 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017476 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17477 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17478 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017479 $Report .= "</div>\n<br/><br/><br/>\n";
17480 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017481 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017482 return $Report;
17483 }
17484 }
17485}
17486
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017487sub getLegend()
17488{
17489 return "<br/>
17490<table class='summary'>
17491<tr>
17492 <td class='new'>added</td>
17493 <td class='passed'>compatible</td>
17494</tr>
17495<tr>
17496 <td class='warning'>warning</td>
17497 <td class='failed'>incompatible</td>
17498</tr></table>\n";
17499}
17500
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017501sub createReport()
17502{
17503 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017504 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017505 writeReport("Join", getReport("Join"));
17506 }
17507 elsif($DoubleReport)
17508 { # default
17509 writeReport("Binary", getReport("Binary"));
17510 writeReport("Source", getReport("Source"));
17511 }
17512 elsif($BinaryOnly)
17513 { # --binary
17514 writeReport("Binary", getReport("Binary"));
17515 }
17516 elsif($SourceOnly)
17517 { # --source
17518 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017519 }
17520}
17521
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017522sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017523{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017524 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017525
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017526 $Footer .= "<hr/>";
17527 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017528 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017529 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017530 $Footer .= "<br/>\n";
17531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017532 return $Footer;
17533}
17534
17535sub get_Report_Problems($$)
17536{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017537 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017538
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017539 my $Report = get_Report_TypeProblems($Severity, $Level);
17540 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017541 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017542 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017543
17544 if($Severity eq "Low" or $Severity eq "Safe") {
17545 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017546 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017547
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017548 if($ReportFormat eq "html")
17549 {
17550 if($Report)
17551 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017552 if($JoinReport)
17553 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017554 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017555 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17556 }
17557 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017558 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017560 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017561 else
17562 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017563 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017564 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17565 }
17566 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017567 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017569 }
17570 }
17571 }
17572 return $Report;
17573}
17574
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017575sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017576{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017577 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17578 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17579 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17580 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017581 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17582 <meta name=\"keywords\" content=\"$Keywords\" />
17583 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017584 <title>
17585 $Title
17586 </title>
17587 <style type=\"text/css\">
17588 $Styles
17589 </style>
17590 <script type=\"text/javascript\" language=\"JavaScript\">
17591 <!--
17592 $Scripts
17593 -->
17594 </script>
17595 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017596}
17597
17598sub insertIDs($)
17599{
17600 my $Text = $_[0];
17601 while($Text=~/CONTENT_ID/)
17602 {
17603 if(int($Content_Counter)%2) {
17604 $ContentID -= 1;
17605 }
17606 $Text=~s/CONTENT_ID/c_$ContentID/;
17607 $ContentID += 1;
17608 $Content_Counter += 1;
17609 }
17610 return $Text;
17611}
17612
17613sub checkPreprocessedUnit($)
17614{
17615 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017616 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017617 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017618 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017619
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017620 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017622 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017623 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017624 chomp($Line);
17625 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017626 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017627 $CurHeader = path_format($1, $OSgroup);
17628 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017629 $CurClass = "";
17630
17631 if(index($CurHeader, $TMP_DIR)==0) {
17632 next;
17633 }
17634
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017635 if(substr($CurHeaderName, 0, 1) eq "<")
17636 { # <built-in>, <command-line>, etc.
17637 $CurHeaderName = "";
17638 $CurHeader = "";
17639 }
17640
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017641 if($ExtraInfo)
17642 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017643 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017644 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17645 }
17646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017647 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017648 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017649 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017650 if($CurHeaderName)
17651 {
17652 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17653 and not $Registered_Headers{$Version}{$CurHeader})
17654 { # not a target
17655 next;
17656 }
17657 if(not is_target_header($CurHeaderName, 1)
17658 and not is_target_header($CurHeaderName, 2))
17659 { # user-defined header
17660 next;
17661 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017662 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017663 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017664
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017665 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017666 {
17667 my ($Name, $Value) = ($1, $2);
17668 if(not $Constants{$Version}{$Name}{"Access"})
17669 {
17670 $Constants{$Version}{$Name}{"Access"} = "public";
17671 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017672 if($CurHeaderName) {
17673 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17674 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017675 }
17676 }
17677 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17678 $Constants{$Version}{$1}{"Access"} = "private";
17679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017680 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017681 else
17682 {
17683 if(defined $ExtraDump)
17684 {
17685 if($Line=~/(\w+)\s*\(/)
17686 { # functions
17687 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17688 }
17689 #elsif($Line=~/(\w+)\s*;/)
17690 #{ # data
17691 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17692 #}
17693 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17694 $CurClass = $2;
17695 }
17696 }
17697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017698 }
17699 close(PREPROC);
17700 foreach my $Constant (keys(%{$Constants{$Version}}))
17701 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017702 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17703 {
17704 delete($Constants{$Version}{$Constant});
17705 next;
17706 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017707 if(not $ExtraDump and ($Constant=~/_h\Z/i
17708 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017709 { # skip
17710 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017711 }
17712 else {
17713 delete($Constants{$Version}{$Constant}{"Access"});
17714 }
17715 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017716 if($Debug)
17717 {
17718 mkpath($DEBUG_PATH{$Version});
17719 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017721}
17722
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017723sub uncoverConstant($$)
17724{
17725 my ($LibVersion, $Constant) = @_;
17726 return "" if(not $LibVersion or not $Constant);
17727 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17728 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17729 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17730 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017731
17732 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017733 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017734 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17735 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017736 {
17737 push(@RecurConstant, $Constant);
17738 my $Uncovered = uncoverConstant($LibVersion, $Value);
17739 if($Uncovered ne "") {
17740 $Value = $Uncovered;
17741 }
17742 pop(@RecurConstant);
17743 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017744
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017745 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017746 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017747 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17748 }
17749 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17750}
17751
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017752sub simpleConstant($$)
17753{
17754 my ($LibVersion, $Value) = @_;
17755 if($Value=~/\W/)
17756 {
17757 my $Value_Copy = $Value;
17758 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17759 {
17760 my $Word = $1;
17761 if($Value!~/$Word\s*\(/)
17762 {
17763 my $Val = uncoverConstant($LibVersion, $Word);
17764 if($Val ne "")
17765 {
17766 $Value=~s/\b$Word\b/$Val/g;
17767 }
17768 }
17769 }
17770 }
17771 return $Value;
17772}
17773
17774sub computeValue($)
17775{
17776 my $Value = $_[0];
17777
17778 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17779 return $1;
17780 }
17781
17782 if($Value=~/\A[\d\-\+()]+\Z/) {
17783 return eval($Value);
17784 }
17785
17786 return $Value;
17787}
17788
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017789my %IgnoreConstant = map {$_=>1} (
17790 "VERSION",
17791 "VERSIONCODE",
17792 "VERNUM",
17793 "VERS_INFO",
17794 "PATCHLEVEL",
17795 "INSTALLPREFIX",
17796 "VBUILD",
17797 "VPATCH",
17798 "VMINOR",
17799 "BUILD_STRING",
17800 "BUILD_TIME",
17801 "PACKAGE_STRING",
17802 "PRODUCTION",
17803 "CONFIGURE_COMMAND",
17804 "INSTALLDIR",
17805 "BINDIR",
17806 "CONFIG_FILE_PATH",
17807 "DATADIR",
17808 "EXTENSION_DIR",
17809 "INCLUDE_PATH",
17810 "LIBDIR",
17811 "LOCALSTATEDIR",
17812 "SBINDIR",
17813 "SYSCONFDIR",
17814 "RELEASE",
17815 "SOURCE_ID",
17816 "SUBMINOR",
17817 "MINOR",
17818 "MINNOR",
17819 "MINORVERSION",
17820 "MAJOR",
17821 "MAJORVERSION",
17822 "MICRO",
17823 "MICROVERSION",
17824 "BINARY_AGE",
17825 "INTERFACE_AGE",
17826 "CORE_ABI",
17827 "PATCH",
17828 "COPYRIGHT",
17829 "TIMESTAMP",
17830 "REVISION",
17831 "PACKAGE_TAG",
17832 "PACKAGEDATE",
17833 "NUMVERSION",
17834 "Release",
17835 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017836);
17837
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017838sub constantFilter($$$)
17839{
17840 my ($Name, $Value, $Level) = @_;
17841
17842 if($Level eq "Binary")
17843 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017844 if($Name=~/_t\Z/)
17845 { # __malloc_ptr_t
17846 return 1;
17847 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017848 foreach (keys(%IgnoreConstant))
17849 {
17850 if($Name=~/(\A|_)$_(_|\Z)/)
17851 { # version
17852 return 1;
17853 }
17854 if(/\A[A-Z].*[a-z]\Z/)
17855 {
17856 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17857 { # version
17858 return 1;
17859 }
17860 }
17861 }
17862 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17863 { # version
17864 return 1;
17865 }
17866 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17867 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17868 return 1;
17869 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017870
17871 if($Value=~/\A["'].*['"]/i)
17872 { # string
17873 return 0;
17874 }
17875
17876 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17877 { # static int gcry_pth_init
17878 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017879 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017880 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017881 return 1;
17882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017883 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017884 { # foo(p)
17885 return 1;
17886 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017887 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017888 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017889 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017890 return 1;
17891 }
17892 }
17893
17894 return 0;
17895}
17896
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017897sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017898{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017899 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017900 foreach my $Constant (keys(%{$Constants{1}}))
17901 {
17902 if($SkipConstants{1}{$Constant})
17903 { # skipped by the user
17904 next;
17905 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017906
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017907 if(my $Header = $Constants{1}{$Constant}{"Header"})
17908 {
17909 if(not is_target_header($Header, 1)
17910 and not is_target_header($Header, 2))
17911 { # user-defined header
17912 next;
17913 }
17914 }
17915 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017916 next;
17917 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017918
17919 my $Old_Value = uncoverConstant(1, $Constant);
17920
17921 if(constantFilter($Constant, $Old_Value, $Level))
17922 { # separate binary and source problems
17923 next;
17924 }
17925
17926 if(not defined $Constants{2}{$Constant}{"Value"})
17927 { # removed
17928 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17929 "Target"=>$Constant,
17930 "Old_Value"=>$Old_Value );
17931 next;
17932 }
17933
17934 if($Constants{2}{$Constant}{"Value"} eq "")
17935 { # empty value
17936 # TODO: implement a rule
17937 next;
17938 }
17939
17940 my $New_Value = uncoverConstant(2, $Constant);
17941
17942 my $Old_Value_Pure = $Old_Value;
17943 my $New_Value_Pure = $New_Value;
17944
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017945 $Old_Value_Pure=~s/(\W)\s+/$1/g;
17946 $Old_Value_Pure=~s/\s+(\W)/$1/g;
17947 $New_Value_Pure=~s/(\W)\s+/$1/g;
17948 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017949
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017950 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017952 if($New_Value_Pure ne $Old_Value_Pure)
17953 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017954 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17955 { # complex values
17956 next;
17957 }
17958 if(computeValue($Old_Value) eq computeValue($New_Value))
17959 { # expressions
17960 next;
17961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017962 if(convert_integer($Old_Value) eq convert_integer($New_Value))
17963 { # 0x0001 and 0x1, 0x1 and 1 equal constants
17964 next;
17965 }
17966 if($Old_Value eq "0" and $New_Value eq "NULL")
17967 { # 0 => NULL
17968 next;
17969 }
17970 if($Old_Value eq "NULL" and $New_Value eq "0")
17971 { # NULL => 0
17972 next;
17973 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017974 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017975 "Target"=>$Constant,
17976 "Old_Value"=>$Old_Value,
17977 "New_Value"=>$New_Value );
17978 }
17979 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017980
17981 foreach my $Constant (keys(%{$Constants{2}}))
17982 {
17983 if(not defined $Constants{1}{$Constant}{"Value"})
17984 {
17985 if($SkipConstants{2}{$Constant})
17986 { # skipped by the user
17987 next;
17988 }
17989
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017990 if(my $Header = $Constants{2}{$Constant}{"Header"})
17991 {
17992 if(not is_target_header($Header, 1)
17993 and not is_target_header($Header, 2))
17994 { # user-defined header
17995 next;
17996 }
17997 }
17998 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017999 next;
18000 }
18001
18002 my $New_Value = uncoverConstant(2, $Constant);
18003 if(not defined $New_Value or $New_Value eq "") {
18004 next;
18005 }
18006
18007 if(constantFilter($Constant, $New_Value, $Level))
18008 { # separate binary and source problems
18009 next;
18010 }
18011
18012 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18013 "Target"=>$Constant,
18014 "New_Value"=>$New_Value );
18015 }
18016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018017}
18018
18019sub convert_integer($)
18020{
18021 my $Value = $_[0];
18022 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018023 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018024 return hex($Value);
18025 }
18026 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018027 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018028 return oct($Value);
18029 }
18030 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018031 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018032 return oct($Value);
18033 }
18034 else {
18035 return $Value;
18036 }
18037}
18038
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018039sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018040{
18041 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018042 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018043 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018044 {
18045 if($LibVersion==1)
18046 {
18047 printMsg("WARNING", "checking headers only");
18048 $CheckHeadersOnly = 1;
18049 }
18050 else {
18051 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18052 }
18053 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018054
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018055 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018056 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018057 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018058
18059 if($CheckUndefined)
18060 {
18061 my %UndefinedLibs = ();
18062
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018063 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18064
18065 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018066 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018067 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018068 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018069 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018070 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018071 if($Symbol_Library{$LibVersion}{$Symbol}
18072 or $DepSymbol_Library{$LibVersion}{$Symbol})
18073 { # exported by target library
18074 next;
18075 }
18076 if(index($Symbol, '@')!=-1)
18077 { # exported default symbol version (@@)
18078 $Symbol=~s/\@/\@\@/;
18079 if($Symbol_Library{$LibVersion}{$Symbol}
18080 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18081 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018082 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018083 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018084 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18085 $UndefinedLibs{$Path} = 1;
18086 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018087 }
18088 }
18089 }
18090 if($ExtraInfo)
18091 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018092 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018093 {
18094 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018095 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018096 foreach (@Paths)
18097 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018098 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018099 my ($Dir, $Name) = separate_path($_);
18100
18101 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018102 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018103 }
18104
18105 $Name = parse_libname($Name, "name", $OStarget);
18106 $Name=~s/\Alib//;
18107
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018108 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018109 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018110
18111 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18112 {
18113 $LibString = " -L".esc($Dir).$LibString;
18114 }
18115
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018116 writeFile($ExtraInfo."/libs-string", $LibString);
18117 }
18118 }
18119 }
18120
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018121 if($ExtraInfo) {
18122 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18123 }
18124
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018125 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018126 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018127 if($#LibPaths!=-1)
18128 {
18129 if(not keys(%{$Symbol_Library{$LibVersion}}))
18130 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018131 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018132 printMsg("WARNING", "checking headers only");
18133 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018134 }
18135 }
18136 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018137
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018138 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018139 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018140}
18141
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018142my %Prefix_Lib_Map=(
18143 # symbols for autodetecting library dependencies (by prefix)
18144 "pthread_" => ["libpthread"],
18145 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18146 "cairo_" => ["libcairo"],
18147 "gtk_" => ["libgtk-x11-2.0"],
18148 "atk_" => ["libatk-1.0"],
18149 "gdk_" => ["libgdk-x11-2.0"],
18150 "gl" => ["libGL"],
18151 "glu" => ["libGLU"],
18152 "popt" => ["libpopt"],
18153 "Py" => ["libpython"],
18154 "jpeg_" => ["libjpeg"],
18155 "BZ2_" => ["libbz2"],
18156 "Fc" => ["libfontconfig"],
18157 "Xft" => ["libXft"],
18158 "SSL_" => ["libssl"],
18159 "sem_" => ["libpthread"],
18160 "snd_" => ["libasound"],
18161 "art_" => ["libart_lgpl_2"],
18162 "dbus_g" => ["libdbus-glib-1"],
18163 "GOMP_" => ["libgomp"],
18164 "omp_" => ["libgomp"],
18165 "cms" => ["liblcms"]
18166);
18167
18168my %Pattern_Lib_Map=(
18169 "SL[a-z]" => ["libslang"]
18170);
18171
18172my %Symbol_Lib_Map=(
18173 # symbols for autodetecting library dependencies (by name)
18174 "pow" => "libm",
18175 "fmod" => "libm",
18176 "sin" => "libm",
18177 "floor" => "libm",
18178 "cos" => "libm",
18179 "dlopen" => "libdl",
18180 "deflate" => "libz",
18181 "inflate" => "libz",
18182 "move_panel" => "libpanel",
18183 "XOpenDisplay" => "libX11",
18184 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018185 "clock_gettime" => "librt",
18186 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018187);
18188
18189sub find_SymbolLibs($$)
18190{
18191 my ($LibVersion, $Symbol) = @_;
18192
18193 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18194 { # debug symbols
18195 return ();
18196 }
18197
18198 my %Paths = ();
18199
18200 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18201 {
18202 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18203 $Paths{$Path} = 1;
18204 }
18205 }
18206
18207 if(my $SymbolPrefix = getPrefix($Symbol))
18208 {
18209 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18210 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18211 }
18212
18213 if(not keys(%Paths))
18214 {
18215 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18216 {
18217 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18218 {
18219 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18220 $Paths{$Path} = 1;
18221 }
18222 }
18223 }
18224 }
18225
18226 if(not keys(%Paths))
18227 {
18228 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18229 {
18230 if($Symbol=~/\A$Prefix/)
18231 {
18232 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18233 {
18234 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18235 $Paths{$Path} = 1;
18236 }
18237 }
18238 }
18239 }
18240 }
18241
18242 if(not keys(%Paths))
18243 {
18244 if($SymbolPrefix)
18245 { # try to find a library by symbol prefix
18246 if($SymbolPrefix eq "inotify" and
18247 index($Symbol, "\@GLIBC")!=-1)
18248 {
18249 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18250 $Paths{$Path} = 1;
18251 }
18252 }
18253 else
18254 {
18255 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18256 $Paths{$Path} = 1;
18257 }
18258 }
18259 }
18260 }
18261
18262 if(my @Paths = keys(%Paths)) {
18263 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18264 }
18265 }
18266 return keys(%Paths);
18267}
18268
18269sub get_LibPath_Prefix($$)
18270{
18271 my ($LibVersion, $Prefix) = @_;
18272
18273 $Prefix = lc($Prefix);
18274 $Prefix=~s/[_]+\Z//g;
18275
18276 foreach ("-2", "2", "-1", "1", "")
18277 { # libgnome-2.so
18278 # libxml2.so
18279 # libdbus-1.so
18280 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18281 return $Path;
18282 }
18283 }
18284 return "";
18285}
18286
18287sub getPrefix($)
18288{
18289 my $Str = $_[0];
18290 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18291 { # XmuValidArea: Xmu
18292 return $1;
18293 }
18294 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18295 { # snfReadFont: snf
18296 return $1;
18297 }
18298 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18299 { # XRRTimes: XRR
18300 return $1;
18301 }
18302 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18303 { # H5HF_delete: H5
18304 return $1;
18305 }
18306 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18307 { # alarm_event_add: alarm_
18308 return $1;
18309 }
18310 elsif($Str=~/\A(([a-z])\2{1,})/i)
18311 { # ffopen
18312 return $1;
18313 }
18314 return "";
18315}
18316
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018317sub getSymbolSize($$)
18318{ # size from the shared library
18319 my ($Symbol, $LibVersion) = @_;
18320 return 0 if(not $Symbol);
18321 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18322 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18323 {
18324 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18325 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18326 {
18327 if($Size<0) {
18328 return -$Size;
18329 }
18330 }
18331 }
18332 return 0;
18333}
18334
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018335sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018336{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18337 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018338 my ($Name, $Type) = @_;
18339
18340 # single
18341 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018342 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018343 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018344 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018346
18347 # double
18348 if($Name=~/$DEFAULT_STD_PARMS/)
18349 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018350 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018351 {
18352 my ($ShortName, $FuncParams) = split_Signature($Name);
18353
18354 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18355 {
18356 if(index($FParam, "<")!=-1)
18357 {
18358 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18359 my $FParam_N = canonifyName($FParam, "T");
18360 if($FParam_N ne $FParam) {
18361 $Name=~s/\Q$FParam\E/$FParam_N/g;
18362 }
18363 }
18364 }
18365 }
18366 elsif($Type eq "T")
18367 {
18368 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18369
18370 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018371 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018372 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018373 my $FParam = $TParams[0];
18374 foreach my $Pos (1 .. $#TParams)
18375 {
18376 my $TParam = $TParams[$Pos];
18377 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18378 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18379 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018380 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018381 }
18382 }
18383 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018384 if($Type eq "S") {
18385 return formatName($Name, "S");
18386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018387 return $Name;
18388}
18389
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018390sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018391{
18392 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018393 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018394 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018395 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018396 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018397 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018398 next if($tr_name{$Symbol});
18399 $Symbol=~s/[\@\$]+(.*)\Z//;
18400 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018401 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018402 elsif(index($Symbol, "?")==0)
18403 {
18404 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018405 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018406 }
18407 else
18408 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018409 $tr_name{$Symbol} = $Symbol;
18410 $mangled_name_gcc{$Symbol} = $Symbol;
18411 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018412 }
18413 }
18414 if($#MnglNames1 > -1)
18415 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018416 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018417 foreach my $MnglName (@MnglNames1)
18418 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018419 if(my $Unmangled = pop(@UnmangledNames))
18420 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018421 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018422 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18423 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18424 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018425 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018426 and $tr_name{$MnglName}=~/vtable for (.+)/)
18427 { # bind class name and v-table symbol
18428 my $ClassName = $1;
18429 $ClassVTable{$ClassName} = $MnglName;
18430 $VTableClass{$MnglName} = $ClassName;
18431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018432 }
18433 }
18434 }
18435 if($#MnglNames2 > -1)
18436 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018437 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018438 foreach my $MnglName (@MnglNames2)
18439 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018440 if(my $Unmangled = pop(@UnmangledNames))
18441 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018442 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018443 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018445 }
18446 }
18447 return \%tr_name;
18448}
18449
18450sub link_symbol($$$)
18451{
18452 my ($Symbol, $RunWith, $Deps) = @_;
18453 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18454 return 1;
18455 }
18456 if($Deps eq "+Deps")
18457 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018458 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018459 return 1;
18460 }
18461 }
18462 return 0;
18463}
18464
18465sub link_symbol_internal($$$)
18466{
18467 my ($Symbol, $RunWith, $Where) = @_;
18468 return 0 if(not $Where or not $Symbol);
18469 if($Where->{$RunWith}{$Symbol})
18470 { # the exact match by symbol name
18471 return 1;
18472 }
18473 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18474 { # indirect symbol version, i.e.
18475 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018476 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018477 if($Where->{$RunWith}{$VSym}) {
18478 return 1;
18479 }
18480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018481 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018482 if($Sym and $Ver)
18483 { # search for the symbol with the same version
18484 # or without version
18485 if($Where->{$RunWith}{$Sym})
18486 { # old: foo@v|foo@@v
18487 # new: foo
18488 return 1;
18489 }
18490 if($Where->{$RunWith}{$Sym."\@".$Ver})
18491 { # old: foo|foo@@v
18492 # new: foo@v
18493 return 1;
18494 }
18495 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18496 { # old: foo|foo@v
18497 # new: foo@@v
18498 return 1;
18499 }
18500 }
18501 return 0;
18502}
18503
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018504sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018505{
18506 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018507 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018508 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018509 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018510 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018511 my $NM = get_CmdPath("nm");
18512 if(not $NM) {
18513 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018514 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018515 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018516 while(<APP>)
18517 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018518 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018519 push(@Imported, $1);
18520 }
18521 }
18522 close(APP);
18523 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018524 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018525 {
18526 my $DumpBinCmd = get_CmdPath("dumpbin");
18527 if(not $DumpBinCmd) {
18528 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18529 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018530 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018531 while(<APP>)
18532 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018533 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18534 push(@Imported, $1);
18535 }
18536 }
18537 close(APP);
18538 }
18539 else
18540 {
18541 my $ReadelfCmd = get_CmdPath("readelf");
18542 if(not $ReadelfCmd) {
18543 exitStatus("Not_Found", "can't find \"readelf\"");
18544 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018545 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018546 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018547 while(<APP>)
18548 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018549 if(defined $symtab)
18550 { # do nothing with symtab
18551 if(index($_, "'.dynsym'")!=-1)
18552 { # dynamic table
18553 $symtab = undef;
18554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018555 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018556 elsif(index($_, "'.symtab'")!=-1)
18557 { # symbol table
18558 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018559 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018560 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018561 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018562 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18563 if($Ndx eq "UND")
18564 { # only imported symbols
18565 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018566 }
18567 }
18568 }
18569 close(APP);
18570 }
18571 return @Imported;
18572}
18573
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018574my %ELF_BIND = map {$_=>1} (
18575 "WEAK",
18576 "GLOBAL"
18577);
18578
18579my %ELF_TYPE = map {$_=>1} (
18580 "FUNC",
18581 "IFUNC",
18582 "OBJECT",
18583 "COMMON"
18584);
18585
18586my %ELF_VIS = map {$_=>1} (
18587 "DEFAULT",
18588 "PROTECTED"
18589);
18590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018591sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018592{ # read the line of 'readelf' output corresponding to the symbol
18593 my @Info = split(/\s+/, $_[0]);
18594 # Num: Value Size Type Bind Vis Ndx Name
18595 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018596 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018597 shift(@Info); # spaces
18598 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018599
18600 if($#Info==7)
18601 { # UND SYMBOL (N)
18602 if($Info[7]=~/\(\d+\)/) {
18603 pop(@Info);
18604 }
18605 }
18606
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018607 if($#Info!=6)
18608 { # other lines
18609 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018610 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018611 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018612 return () if(not defined $ELF_BIND{$Info[3]});
18613 return () if(not defined $ELF_VIS{$Info[4]});
18614 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18615 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18616 return ();
18617 }
18618 if($OStarget eq "symbian")
18619 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18620 if(index($Info[6], "_._.absent_export_")!=-1)
18621 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18622 return ();
18623 }
18624 $Info[6]=~s/\@.+//g; # remove version
18625 }
18626 if(index($Info[2], "0x") == 0)
18627 { # size == 0x3d158
18628 $Info[2] = hex($Info[2]);
18629 }
18630 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018631}
18632
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018633sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018634{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018635 my ($LibVersion, $Name) = @_;
18636 return "" if(not $LibVersion or not $Name);
18637 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18638 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018639 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018640 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18641}
18642
18643sub get_LibPath_I($$)
18644{
18645 my ($LibVersion, $Name) = @_;
18646 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018647 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018648 if(-f $Name)
18649 { # absolute path
18650 return $Name;
18651 }
18652 else
18653 { # broken
18654 return "";
18655 }
18656 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018657 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018658 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018659 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018660 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018661 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018662 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018663 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018664 }
18665 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18666 { # ldconfig default paths
18667 return $DefaultPath;
18668 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018669 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018670 { # search in default linker directories
18671 # and then in all system paths
18672 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018673 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018674 }
18675 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018676 if(not defined $Cache{"checkSystemFiles"}) {
18677 checkSystemFiles();
18678 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018679 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18680 return $AllObjects[0];
18681 }
18682 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18683 {
18684 if($ShortName ne $Name)
18685 { # FIXME: check this case
18686 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18687 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018688 }
18689 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018690 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018691 # can't find
18692 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018693}
18694
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018695sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018696{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018697 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18698 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018699
18700 my $Real_Path = realpath($Lib_Path);
18701
18702 if(not $Real_Path)
18703 { # broken link
18704 return ();
18705 }
18706
18707 my $Lib_Name = get_filename($Real_Path);
18708
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018709 if($ExtraInfo)
18710 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018711 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018712 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018713 }
18714
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018715 if($IsNeededLib)
18716 {
18717 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18718 return ();
18719 }
18720 }
18721 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018722 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018723
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018724 push(@RecurLib, $Lib_Name);
18725 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018726 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18727
18728 if(not $IsNeededLib)
18729 { # special cases: libstdc++ and libc
18730 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18731 {
18732 if($ShortName eq "libstdc++")
18733 { # libstdc++.so.6
18734 $STDCXX_TESTING = 1;
18735 }
18736 elsif($ShortName eq "libc")
18737 { # libc-2.11.3.so
18738 $GLIBC_TESTING = 1;
18739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018740 }
18741 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018742 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018743 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018744 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018745 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018746 mkpath(get_dirname($DebugPath));
18747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018748 if($OStarget eq "macos")
18749 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018750 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018751 if(not $NM) {
18752 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018753 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018754 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018755 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018756 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018757 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018758 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018759 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018760 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018761 else
18762 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018763 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018764 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018765 while(<LIB>)
18766 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018767 if($CheckUndefined)
18768 {
18769 if(not $IsNeededLib)
18770 {
18771 if(/ U _([\w\$]+)\s*\Z/)
18772 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018773 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018774 next;
18775 }
18776 }
18777 }
18778
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018779 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018780 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018781 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018782 if($IsNeededLib)
18783 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018784 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018785 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018786 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18787 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018789 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018790 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018791 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018792 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18793 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018794 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18795 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018796 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018797 setLanguage($LibVersion, "C++");
18798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018800 }
18801 }
18802 }
18803 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018804
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018805 if($Deps)
18806 {
18807 if($LIB_TYPE eq "dynamic")
18808 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018809
18810 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018811 if(not $OtoolCmd) {
18812 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018813 }
18814
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018815 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18816 while(<LIB>)
18817 {
18818 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18819 and $1 ne $Lib_Path) {
18820 $NeededLib{$1} = 1;
18821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018822 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018823 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018825 }
18826 }
18827 elsif($OStarget eq "windows")
18828 { # Windows *.dll, *.lib
18829 my $DumpBinCmd = get_CmdPath("dumpbin");
18830 if(not $DumpBinCmd) {
18831 exitStatus("Not_Found", "can't find \"dumpbin\"");
18832 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018833 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018834 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018835 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018836 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018837 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018838 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018839 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018840 else
18841 { # write to pipe
18842 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844 while(<LIB>)
18845 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18846 # 1198 4AD SetThreadToken (forwarded to ...)
18847 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018848 # 1 0 00005B30 ??0?N = ... (with pdb)
18849 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018850 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018851 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018852 { # dynamic, static and forwarded symbols
18853 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018854 if($IsNeededLib)
18855 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018856 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018857 {
18858 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18859 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018861 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018862 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018863 {
18864 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18865 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018866 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18867 {
18868 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18869 setLanguage($LibVersion, "C++");
18870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018872 }
18873 }
18874 }
18875 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018876
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018877 if($Deps)
18878 {
18879 if($LIB_TYPE eq "dynamic")
18880 { # dependencies
18881 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18882 while(<LIB>)
18883 {
18884 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18885 and $1 ne $Lib_Path) {
18886 $NeededLib{path_format($1, $OSgroup)} = 1;
18887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018889 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 }
18892 }
18893 else
18894 { # Unix; *.so, *.a
18895 # Symbian: *.dso, *.lib
18896 my $ReadelfCmd = get_CmdPath("readelf");
18897 if(not $ReadelfCmd) {
18898 exitStatus("Not_Found", "can't find \"readelf\"");
18899 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018900 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018901 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018902 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018903 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018904 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018905 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018906 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018907 else
18908 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018909 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018910 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018911 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 while(<LIB>)
18913 {
18914 if($LIB_TYPE eq "dynamic")
18915 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018916 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018917 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018918 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018919 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018920 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018921 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 # do nothing with symtab
18923 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018924 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018925 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018926 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018927 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018928 next;
18929 }
18930 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018931 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018932 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018933 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018934 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018935 if($CheckUndefined)
18936 {
18937 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018938 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018939 }
18940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941 next;
18942 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018943 if($Bind eq "WEAK")
18944 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018945 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018946 if($Weak eq "-Weak")
18947 { # skip WEAK symbols
18948 next;
18949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018950 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018951 my $Short = $Symbol;
18952 $Short=~s/\@.+//g;
18953 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018954 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018955 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18956 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018957 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018958 if($IsNeededLib)
18959 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018960 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018961 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18963 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018965 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018966 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018967 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018968 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18969 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18970 if($Vers)
18971 {
18972 if($LIB_EXT eq "so")
18973 { # value
18974 $Interface_Value{$LibVersion}{$Symbol} = $Value;
18975 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
18976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018977 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018978 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18979 {
18980 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18981 setLanguage($LibVersion, "C++");
18982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018984 }
18985 }
18986 }
18987 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018988
18989 if($Deps and $LIB_TYPE eq "dynamic")
18990 { # dynamic library specifics
18991 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
18992 open(LIB, $Cmd." |");
18993
18994 while(<LIB>)
18995 {
18996 if(/NEEDED.+\[([^\[\]]+)\]/)
18997 { # dependencies:
18998 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
18999 $NeededLib{$1} = 1;
19000 }
19001 }
19002
19003 close(LIB);
19004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019005 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019006 if($Vers)
19007 {
19008 if(not $IsNeededLib and $LIB_EXT eq "so")
19009 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019010 my %Found = ();
19011
19012 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019013 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019014 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019015 next if(index($Symbol,"\@")==-1);
19016 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019017 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019019 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019020 if($Symbol_SameValue ne $Symbol
19021 and index($Symbol_SameValue,"\@")==-1)
19022 {
19023 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019024 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019025 last;
19026 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019027 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019028 }
19029 }
19030
19031 # default
19032 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19033 {
19034 next if(defined $Found{$Symbol});
19035 next if(index($Symbol,"\@\@")==-1);
19036
19037 if($Symbol=~/\A([^\@]*)\@\@/
19038 and not $SymVer{$LibVersion}{$1})
19039 {
19040 $SymVer{$LibVersion}{$1} = $Symbol;
19041 $Found{$Symbol} = 1;
19042 }
19043 }
19044
19045 # non-default
19046 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19047 {
19048 next if(defined $Found{$Symbol});
19049 next if(index($Symbol,"\@")==-1);
19050
19051 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19052 and not $SymVer{$LibVersion}{$1})
19053 {
19054 $SymVer{$LibVersion}{$1} = $Symbol;
19055 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019056 }
19057 }
19058 }
19059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019060 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019061 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019062 foreach my $DyLib (sort keys(%NeededLib))
19063 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019064 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19065
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019066 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19067 {
19068 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19069 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19070 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072 }
19073 }
19074 pop(@RecurLib);
19075 return $Library_Symbol{$LibVersion};
19076}
19077
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019078sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019079{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019080 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019082 return keys(%Prefixes);
19083}
19084
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019085sub get_prefixes_I($$)
19086{
19087 foreach my $P (@{$_[0]})
19088 {
19089 my @Parts = reverse(split(/[\/\\]+/, $P));
19090 my $Name = $Parts[0];
19091 foreach (1 .. $#Parts)
19092 {
19093 $_[1]->{$Name}{$P} = 1;
19094 last if($_>4 or $Parts[$_] eq "include");
19095 $Name = $Parts[$_].$SLASH.$Name;
19096 }
19097 }
19098}
19099
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019100sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019101{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019102 $Cache{"checkSystemFiles"} = 1;
19103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019104 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019105
19106 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019107 {
19108 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019109
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019110 my @Files = cmd_find($DevelPath,"f");
19111 foreach my $Link (cmd_find($DevelPath,"l"))
19112 { # add symbolic links
19113 if(-f $Link) {
19114 push(@Files, $Link);
19115 }
19116 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019117
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019118 # search for headers in /usr/lib
19119 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19120 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19121 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019122
19123 # search for libraries in /usr/lib (including symbolic links)
19124 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19125 foreach my $Path (@Libs)
19126 {
19127 my $N = get_filename($Path);
19128 $SystemObjects{$N}{$Path} = 1;
19129 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019130 }
19131 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019132
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019133 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019135 next if(not -d $DevelPath);
19136 # search for all header files in the /usr/include
19137 # with or without extension (ncurses.h, QtCore, ...)
19138 push(@SysHeaders, cmd_find($DevelPath,"f"));
19139 foreach my $Link (cmd_find($DevelPath,"l"))
19140 { # add symbolic links
19141 if(-f $Link) {
19142 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 }
19145 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019146 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019147}
19148
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019149sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019150{
19151 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019152 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019153 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19154 {
19155 if(not -e $Dest) {
19156 exitStatus("Access_Error", "can't access \'$Dest\'");
19157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019158 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019159 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19160 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019161 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019162 }
19163 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019164 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165}
19166
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019167sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168{
19169 my ($Path, $LibVersion) = @_;
19170 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019171 my $Name = get_filename($Path);
19172 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 return 1;
19174 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019175 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019176 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19177 return 1;
19178 }
19179 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19180 {
19181 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19182 return 1;
19183 }
19184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019185 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019186 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019187 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019188 return 1;
19189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019190 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019191 return 1;
19192 }
19193 }
19194 return 0;
19195}
19196
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019197sub specificHeader($$)
19198{
19199 my ($Header, $Spec) = @_;
19200 my $Name = get_filename($Header);
19201
19202 if($Spec eq "windows")
19203 {# MS Windows
19204 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19205 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19206 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19207 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19208 my @Dirs = (
19209 "win32",
19210 "win64",
19211 "win",
19212 "windows",
19213 "msvcrt"
19214 ); # /gsf-win32/
19215 if(my $DIRs = join("|", @Dirs)) {
19216 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19217 }
19218 }
19219 elsif($Spec eq "macos")
19220 { # Mac OS
19221 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19222 }
19223
19224 return 0;
19225}
19226
19227sub skipAlienHeader($)
19228{
19229 my $Path = $_[0];
19230 my $Name = get_filename($Path);
19231 my $Dir = get_dirname($Path);
19232
19233 if($Tolerance=~/2/)
19234 { # 2 - skip internal headers
19235 my @Terms = (
19236 "p",
19237 "priv",
19238 "int",
19239 "impl",
19240 "implementation",
19241 "internal",
19242 "private",
19243 "old",
19244 "compat",
19245 "debug",
19246 "test",
19247 "gen"
19248 );
19249
19250 my @Dirs = (
19251 "private",
19252 "priv",
19253 "port",
19254 "impl",
19255 "internal",
19256 "detail",
19257 "details",
19258 "old",
19259 "compat",
19260 "debug",
19261 "config",
19262 "compiler",
19263 "platform",
19264 "test"
19265 );
19266
19267 if(my $TERMs = join("|", @Terms)) {
19268 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19269 }
19270 if(my $DIRs = join("|", @Dirs)) {
19271 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19272 }
19273
19274 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19275 }
19276
19277 if($Tolerance=~/1/)
19278 { # 1 - skip non-Linux headers
19279 if($OSgroup ne "windows")
19280 {
19281 if(specificHeader($Path, "windows")) {
19282 return 1;
19283 }
19284 }
19285 if($OSgroup ne "macos")
19286 {
19287 if(specificHeader($Path, "macos")) {
19288 return 1;
19289 }
19290 }
19291 }
19292
19293 # valid
19294 return 0;
19295}
19296
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019297sub skipHeader($$)
19298{
19299 my ($Path, $LibVersion) = @_;
19300 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019301 if(defined $Cache{"skipHeader"}{$Path}) {
19302 return $Cache{"skipHeader"}{$Path};
19303 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019304 if(defined $Tolerance and $Tolerance=~/1|2/)
19305 { # --tolerant
19306 if(skipAlienHeader($Path)) {
19307 return ($Cache{"skipHeader"}{$Path} = 1);
19308 }
19309 }
19310 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19311 return 0;
19312 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019313 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19314}
19315
19316sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019317{ # returns:
19318 # 1 - if header should NOT be included and checked
19319 # 2 - if header should NOT be included, but should be checked
19320 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019321 my $Name = get_filename($Path);
19322 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019323 return $Kind;
19324 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019325 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19326 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019327 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019328 if(index($Path, $D)!=-1)
19329 {
19330 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19331 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019333 }
19334 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019335 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19336 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019337 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019338 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19339 {
19340 if($Name=~/$P/) {
19341 return $Kind;
19342 }
19343 if($P=~/[\/\\]/ and $Path=~/$P/) {
19344 return $Kind;
19345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019346 }
19347 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019349 return 0;
19350}
19351
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019352sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019353{
19354 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019355 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019356 { # system directory
19357 return;
19358 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019359 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019360 { # already registered
19361 return;
19362 }
19363 foreach my $Path (find_libs($Dir,"",1))
19364 {
19365 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019366 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019367 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019368 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019369 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19370}
19371
19372sub registerObject($$)
19373{
19374 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019375
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019376 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019377 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019378 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019379 {
19380 if(my $SONAME = getSONAME($Path)) {
19381 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19382 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019383 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019384 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19385 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019386 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019387
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019388 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019389 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019390 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019391 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019392 if($ObjArch ne getArch_GCC($LibVersion))
19393 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19394 $CheckedArch{$LibVersion} = 1;
19395 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 +040019396 }
19397 }
19398 }
19399}
19400
19401sub getArch_Object($)
19402{
19403 my $Path = $_[0];
19404
19405 my %MachineType = (
19406 "14C" => "x86",
19407 "8664" => "x86_64",
19408 "1C0" => "arm",
19409 "200" => "ia64"
19410 );
19411
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019412 my %ArchName = (
19413 "s390:31-bit" => "s390",
19414 "s390:64-bit" => "s390x",
19415 "powerpc:common" => "ppc32",
19416 "powerpc:common64" => "ppc64",
19417 "i386:x86-64" => "x86_64",
19418 "mips:3000" => "mips",
19419 "sparc:v8plus" => "sparcv9"
19420 );
19421
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019422 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019423 {
19424 my $DumpbinCmd = get_CmdPath("dumpbin");
19425 if(not $DumpbinCmd) {
19426 exitStatus("Not_Found", "can't find \"dumpbin\"");
19427 }
19428
19429 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19430 my $Out = `$Cmd`;
19431
19432 if($Out=~/(\w+)\smachine/)
19433 {
19434 if(my $Type = $MachineType{uc($1)})
19435 {
19436 return $Type;
19437 }
19438 }
19439 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019440 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019441 {
19442 my $ObjdumpCmd = get_CmdPath("objdump");
19443 if(not $ObjdumpCmd) {
19444 exitStatus("Not_Found", "can't find \"objdump\"");
19445 }
19446
19447 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019448
19449 if($OSgroup eq "windows") {
19450 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19451 }
19452 else {
19453 $Cmd = "LANG=$LOCALE ".$Cmd;
19454 }
19455 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019456
19457 if($Out=~/architecture:\s+([\w\-\:]+)/)
19458 {
19459 my $Arch = $1;
19460 if($Arch=~s/\:(.+)//)
19461 {
19462 my $Suffix = $1;
19463
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019464 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019465 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019466 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019467 }
19468 }
19469
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019470 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019471 $Arch = "x86";
19472 }
19473
19474 if($Arch eq "x86-64") {
19475 $Arch = "x86_64";
19476 }
19477
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019478 if($Arch eq "ia64-elf64") {
19479 $Arch = "ia64";
19480 }
19481
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019482 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019483 }
19484 }
19485 else
19486 { # macos, etc.
19487 # TODO
19488 }
19489
19490 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019491}
19492
19493sub getSONAME($)
19494{
19495 my $Path = $_[0];
19496 return if(not $Path);
19497 if(defined $Cache{"getSONAME"}{$Path}) {
19498 return $Cache{"getSONAME"}{$Path};
19499 }
19500 my $ObjdumpCmd = get_CmdPath("objdump");
19501 if(not $ObjdumpCmd) {
19502 exitStatus("Not_Found", "can't find \"objdump\"");
19503 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019504 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019505 if($OSgroup eq "windows") {
19506 $SonameCmd .= " | find \"SONAME\"";
19507 }
19508 else {
19509 $SonameCmd .= " | grep SONAME";
19510 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019511 if(my $SonameInfo = `$SonameCmd`)
19512 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019513 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19514 return ($Cache{"getSONAME"}{$Path} = $1);
19515 }
19516 }
19517 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019518}
19519
19520sub getSOPaths_Dest($$)
19521{
19522 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019523 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019524 return ();
19525 }
19526 if(-f $Dest)
19527 {
19528 if(not parse_libname($Dest, "name", $OStarget)) {
19529 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19530 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019531 registerObject($Dest, $LibVersion);
19532 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019533 return ($Dest);
19534 }
19535 elsif(-d $Dest)
19536 {
19537 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019538 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019539 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019540 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19541 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019542 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019543 { # all files and symlinks that match the name of a library
19544 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19545 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019546 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019547 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019548 }
19549 }
19550 }
19551 else
19552 { # search for all files and symlinks
19553 foreach my $Path (find_libs($Dest,"",""))
19554 {
19555 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019556 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019557 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019558 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019559 }
19560 if($OSgroup eq "macos")
19561 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019562 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019563 {
19564 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019565 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019566 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019567 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19568 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019569 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019570 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019571 }
19572 }
19573 }
19574 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019575 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019576 }
19577 else {
19578 return ();
19579 }
19580}
19581
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019582sub isCyclical($$)
19583{
19584 my ($Stack, $Value) = @_;
19585 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019586}
19587
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019588sub getGCC_Opts($)
19589{ # to use in module
19590 my $LibVersion = $_[0];
19591
19592 my @Opts = ();
19593
19594 if($CompilerOptions{$LibVersion})
19595 { # user-defined options
19596 push(@Opts, $CompilerOptions{$LibVersion});
19597 }
19598 if($GccOptions)
19599 { # additional
19600 push(@Opts, $GccOptions);
19601 }
19602
19603 if(@Opts) {
19604 return join(" ", @Opts);
19605 }
19606
19607 return undef;
19608}
19609
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019610sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019611{
19612 my $LibVersion = $_[0];
19613
19614 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19615 return $Cache{"getArch_GCC"}{$LibVersion};
19616 }
19617
19618 my $Arch = undef;
19619
19620 if($GCC_PATH)
19621 {
19622 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19623
19624 my $Cmd = $GCC_PATH." test.c -o test";
19625 if(my $Opts = getGCC_Opts($LibVersion))
19626 { # user-defined options
19627 $Cmd .= " ".$Opts;
19628 }
19629
19630 chdir($TMP_DIR);
19631 system($Cmd);
19632 chdir($ORIG_DIR);
19633
19634 $Arch = getArch_Object("$TMP_DIR/test");
19635
19636 unlink("$TMP_DIR/test.c");
19637 unlink("$TMP_DIR/test");
19638 }
19639
19640 if(not $Arch) {
19641 exitStatus("Error", "can't check ARCH type");
19642 }
19643
19644 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19645}
19646
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019647sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019648{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019649 my $LibVersion = $_[0];
19650
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019651 my $Size = undef;
19652
19653 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019654 if(my $Arch = getArch($LibVersion))
19655 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019656 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019657 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019658 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019659 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19660 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019661 }
19662 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019663
19664 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019665 {
19666 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019667
19668 my $Cmd = $GCC_PATH." -E -dD empty.h";
19669 if(my $Opts = getGCC_Opts($LibVersion))
19670 { # user-defined options
19671 $Cmd .= " ".$Opts;
19672 }
19673
19674 chdir($TMP_DIR);
19675 my $Defines = `$Cmd`;
19676 chdir($ORIG_DIR);
19677
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019678 unlink("$TMP_DIR/empty.h");
19679
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019680 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19681 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019682 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019683 }
19684 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19685 { # GCC 3
19686 my $PTRDIFF = $1;
19687 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019688 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019689 }
19690 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019691 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019692 }
19693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019694 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019695
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019696 if(not $Size) {
19697 exitStatus("Error", "can't check WORD size");
19698 }
19699
19700 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019701}
19702
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019703sub getWordSize($)
19704{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019705 return $WORD_SIZE{$_[0]};
19706}
19707
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019708sub majorVersion($)
19709{
19710 my $V = $_[0];
19711 return 0 if(not $V);
19712 my @VParts = split(/\./, $V);
19713 return $VParts[0];
19714}
19715
19716sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019717{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019718 my ($V1, $V2) = @_;
19719 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019720 my @V1Parts = split(/\./, $V1);
19721 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019722 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19723 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019724 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19725 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19726 }
19727 return -1 if($#V1Parts < $#V2Parts);
19728 return 1 if($#V1Parts > $#V2Parts);
19729 return 0;
19730}
19731
19732sub read_ABI_Dump($$)
19733{
19734 my ($LibVersion, $Path) = @_;
19735 return if(not $LibVersion or not -e $Path);
19736 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019737 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019738 { # input *.abi
19739 $FilePath = $Path;
19740 }
19741 else
19742 { # input *.abi.tar.gz
19743 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019744 if(not isDump_U($FilePath)) {
19745 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019747 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019748
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019749 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019750
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019751 my $Line = readLineNum($FilePath, 0);
19752 if($Line=~/xml/)
19753 { # XML format
19754 loadModule("XmlDump");
19755 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019756 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019757 else
19758 { # Perl Data::Dumper format (default)
19759 open(DUMP, $FilePath);
19760 local $/ = undef;
19761 my $Content = <DUMP>;
19762 close(DUMP);
19763
19764 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19765 { # remove temp file
19766 unlink($FilePath);
19767 }
19768 if($Content!~/};\s*\Z/) {
19769 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19770 }
19771 $ABI = eval($Content);
19772 if(not $ABI) {
19773 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019775 }
19776 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019777 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019778 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019779 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019781 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019783 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019784 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019785
19786 if($ABI->{"ABI_DUMP_VERSION"})
19787 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019788 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019789 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019790 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019792 }
19793 else
19794 { # support for old ABI dumps
19795 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019796 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019797 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019798 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019799 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019800
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019801 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019802 {
19803 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 +040019804 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019805
19806 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19807 { # DWARF ABI Dump
19808 $UseConv_Real{$LibVersion}{"P"} = 1;
19809 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19810
19811 $UsedDump{$LibVersion}{"DWARF"} = 1;
19812
19813 $TargetComponent = "module";
19814 }
19815
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019816 if(not checkDump($LibVersion, "2.11"))
19817 { # old ABI dumps
19818 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019819 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019820 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019821 { # ABI dump created with --binary option
19822 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19823 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019824 else
19825 { # default
19826 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19827 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019828
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019829 if(defined $ABI->{"Mode"}
19830 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019831 { # --ext option
19832 $ExtendedCheck = 1;
19833 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019834 if($ABI->{"Extra"}) {
19835 $ExtraDump = 1;
19836 }
19837
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019838 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019839 {
19840 $UsedDump{$LibVersion}{"L"} = $Lang;
19841 setLanguage($LibVersion, $Lang);
19842 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019843 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019844 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019845 }
19846 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019847 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019848 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019849 if(not $TInfo)
19850 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019851 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019852 }
19853 my %Tid_TDid = ();
19854 foreach my $TDid (keys(%{$TInfo}))
19855 {
19856 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19857 {
19858 $MAX_ID = $Tid if($Tid>$MAX_ID);
19859 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019860 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019861 }
19862 }
19863 my %NewID = ();
19864 foreach my $Tid (keys(%Tid_TDid))
19865 {
19866 my @TDids = keys(%{$Tid_TDid{$Tid}});
19867 if($#TDids>=1)
19868 {
19869 foreach my $TDid (@TDids)
19870 {
19871 if($TDid) {
19872 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19873 }
19874 else
19875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019876 my $ID = ++$MAX_ID;
19877
19878 $NewID{$TDid}{$Tid} = $ID;
19879 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19880 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019881 }
19882 }
19883 }
19884 else
19885 {
19886 my $TDid = $TDids[0];
19887 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19888 }
19889 }
19890 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19891 {
19892 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19893 if(defined $Info{"BaseType"})
19894 {
19895 my $Bid = $Info{"BaseType"}{"Tid"};
19896 my $BDid = $Info{"BaseType"}{"TDid"};
19897 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019898 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019899 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19900 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019902 }
19903 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19904 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019905 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019906 read_Machine_DumpInfo($ABI, $LibVersion);
19907 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019908 if(not $SymbolInfo{$LibVersion})
19909 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019910 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019911 }
19912 if(not keys(%{$SymbolInfo{$LibVersion}}))
19913 { # validation of old-version dumps
19914 if(not $ExtendedCheck) {
19915 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19916 }
19917 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019918 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019919 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019920 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019921 else
19922 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019923 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019924 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019925 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019926 }
19927 if(not $DepSymbols)
19928 { # Cannot reconstruct DepSymbols. This may result in false
19929 # positives if the old dump is for library 2. Not a problem if
19930 # old dumps are only from old libraries.
19931 $DepSymbols = {};
19932 }
19933 foreach my $Symbol (keys(%{$DepSymbols})) {
19934 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19935 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019936 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019937 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040019938
19939 if(my $V = $TargetVersion{$LibVersion}) {
19940 $Descriptor{$LibVersion}{"Version"} = $V;
19941 }
19942 else {
19943 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19944 }
19945
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019946 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019947 if(not $SkipTypes{$LibVersion})
19948 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019949 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019950 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019952 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019953 { # if not defined by -skip-symbols option
19954 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
19955 if(not $SkipSymbols{$LibVersion})
19956 { # support for old dumps
19957 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
19958 }
19959 if(not $SkipSymbols{$LibVersion})
19960 { # support for old dumps
19961 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
19962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019963 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019964 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019965
19966 if(not $TargetHeaders{$LibVersion})
19967 { # if not defined by -headers-list option
19968 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19969 }
19970
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019971 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019972 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019973 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019974 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019975 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019976 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019977 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019978 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019979 if(not checkDump($LibVersion, "2.10.1")
19980 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019981 { # support for old ABI dumps: added target headers
19982 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019983 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019984 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019985 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019986 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019988 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019989 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019990 if(defined $ABI->{"GccConstants"})
19991 { # 3.0
19992 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19993 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19994 }
19995 }
19996
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019997 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019998 if(not $NestedNameSpaces{$LibVersion})
19999 { # support for old dumps
20000 # Cannot reconstruct NameSpaces. This may affect design
20001 # of the compatibility report.
20002 $NestedNameSpaces{$LibVersion} = {};
20003 }
20004 # target system type
20005 # needed to adopt HTML report
20006 if(not $DumpSystem)
20007 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020008 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020009 }
20010 # recreate environment
20011 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20012 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020013 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020014 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020015 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20016 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020017 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020018 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020020 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20021 {
20022 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20023 setLanguage($LibVersion, "C++");
20024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020025 }
20026 }
20027 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020028 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20029 {
20030 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20031 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20032 }
20033 }
20034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020035 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020036 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020037 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020038 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020039 {
20040 if(not $Symbol_Library{$LibVersion}{$MnglName}
20041 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20042 push(@VFunc, $MnglName);
20043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020044 }
20045 }
20046 translateSymbols(@VFunc, $LibVersion);
20047 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020048 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20049
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020050 if(not checkDump($LibVersion, "3.0"))
20051 { # support for old ABI dumps
20052 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20053 {
20054 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20055 {
20056 if(ref($BaseType) eq "HASH") {
20057 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20058 }
20059 }
20060 }
20061 }
20062
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020063 if(not checkDump($LibVersion, "3.2"))
20064 { # support for old ABI dumps
20065 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20066 {
20067 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20068 {
20069 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20070 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20071 }
20072 }
20073 }
20074
20075 # repair target headers list
20076 delete($TargetHeaders{$LibVersion});
20077 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020078 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20079 }
20080 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20081 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020082 }
20083
20084 # non-target constants from anon enums
20085 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20086 {
20087 if(not $ExtraDump
20088 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20089 {
20090 delete($Constants{$LibVersion}{$Name});
20091 }
20092 }
20093 }
20094
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020095 if(not checkDump($LibVersion, "2.20"))
20096 { # support for old ABI dumps
20097 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20098 {
20099 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20100
20101 if($TType=~/Struct|Union|Enum|Typedef/)
20102 { # repair complex types first
20103 next;
20104 }
20105
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020106 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020107 {
20108 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20109 if($BType=~/Struct|Union|Enum/i)
20110 {
20111 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20112 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20113 }
20114 }
20115 }
20116 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20117 {
20118 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20119 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20120 if($TType=~/Struct|Union|Enum/) {
20121 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20122 }
20123 }
20124 }
20125
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020126 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020127 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020128 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20129 { # support for old ABI dumps < 2.0 (ACC 1.22)
20130 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20131 {
20132 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20133 {
20134 if($Access ne "public") {
20135 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20136 }
20137 }
20138 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20139 }
20140 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20141 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020142 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20143 { # support for old ABI dumps
20144 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20145 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020146 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20147 { # DWARF ABI Dumps
20148 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20149 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020150 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20151 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20152 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020153 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20154 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020155 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020156 foreach (keys(%{$TInfo{"Base"}})) {
20157 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020159 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020160 if($TInfo{"Type"} eq "MethodPtr")
20161 {
20162 if(defined $TInfo{"Param"})
20163 { # support for old ABI dumps <= 1.17
20164 if(not defined $TInfo{"Param"}{"0"})
20165 {
20166 my $Max = keys(%{$TInfo{"Param"}});
20167 foreach my $Pos (1 .. $Max) {
20168 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20169 }
20170 delete($TInfo{"Param"}{$Max});
20171 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20172 }
20173 }
20174 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020175 if($TInfo{"BaseType"} eq $TypeId)
20176 { # fix ABI dump
20177 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20178 }
20179 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020180 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020181 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020182 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020183 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20184 if(not $BName)
20185 { # broken type
20186 next;
20187 }
20188 if($TInfo{"Name"} eq $BName)
20189 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020190 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020191 next;
20192 }
20193 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20194 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020195 }
20196 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020197 }
20198 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20199 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020200 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020201 }
20202 }
20203
20204 if(not checkDump($LibVersion, "2.15"))
20205 { # support for old ABI dumps
20206 my %Dups = ();
20207 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20208 {
20209 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020210 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020211 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20212 { # remove template decls
20213 delete($SymbolInfo{$LibVersion}{$InfoId});
20214 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020216 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020217 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20218 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020219 { # templates
20220 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020221 }
20222 }
20223 }
20224
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020225 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20226 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020227 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20228 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20229 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20230 { # support for old ABI dumps (< 3.1)
20231 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20232 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20233 { # add "this" first parameter
20234 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20235 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20236
20237 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20238 {
20239 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20240 foreach my $Pos (reverse(0 .. $#Pos)) {
20241 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20242 }
20243 }
20244 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20245 }
20246 }
20247
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020248 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20249 { # ABI dumps have no mangled names for C-functions
20250 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020252 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20253 { # support for old ABI dumps
20254 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20255 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020256 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20257 { # DWARF ABI Dumps
20258 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20259 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020260 }
20261
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 $Descriptor{$LibVersion}{"Dump"} = 1;
20263}
20264
20265sub read_Machine_DumpInfo($$)
20266{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 my ($ABI, $LibVersion) = @_;
20268 if($ABI->{"Arch"}) {
20269 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020270 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020271 if($ABI->{"WordSize"}) {
20272 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020273 }
20274 else
20275 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020276 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020277 }
20278 if(not $WORD_SIZE{$LibVersion})
20279 { # support for old dumps (<1.23)
20280 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20281 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020282 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020283 }
20284 else
20285 {
20286 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020287 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020288 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020289 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20290 { # any "pointer"-type
20291 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020292 last;
20293 }
20294 }
20295 if($PSize)
20296 { # a pointer type size
20297 $WORD_SIZE{$LibVersion} = $PSize;
20298 }
20299 else {
20300 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20301 }
20302 }
20303 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020304 if($ABI->{"GccVersion"}) {
20305 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020306 }
20307}
20308
20309sub read_Libs_DumpInfo($$)
20310{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020311 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020312 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20313 if(not $Library_Symbol{$LibVersion})
20314 { # support for old dumps
20315 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020317 if(keys(%{$Library_Symbol{$LibVersion}})
20318 and not $DumpAPI) {
20319 $Descriptor{$LibVersion}{"Libs"} = "OK";
20320 }
20321}
20322
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020323sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020324{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020325 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020326
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020327 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020328 and not $DumpAPI) {
20329 $Descriptor{$LibVersion}{"Headers"} = "OK";
20330 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020331 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020332 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020333 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020334 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020335 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020336
20337 if(keys(%{$ABI->{"Sources"}})
20338 and not $DumpAPI) {
20339 $Descriptor{$LibVersion}{"Sources"} = "OK";
20340 }
20341 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020342 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020343 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20344 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346}
20347
20348sub find_libs($$$)
20349{
20350 my ($Path, $Type, $MaxDepth) = @_;
20351 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020352 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020353}
20354
20355sub createDescriptor($$)
20356{
20357 my ($LibVersion, $Path) = @_;
20358 if(not $LibVersion or not $Path
20359 or not -e $Path) {
20360 return "";
20361 }
20362 if(-d $Path)
20363 { # directory with headers files and shared objects
20364 return "
20365 <version>
20366 ".$TargetVersion{$LibVersion}."
20367 </version>
20368
20369 <headers>
20370 $Path
20371 </headers>
20372
20373 <libs>
20374 $Path
20375 </libs>";
20376 }
20377 else
20378 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020379 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020380 { # standard XML-descriptor
20381 return readFile($Path);
20382 }
20383 elsif(is_header($Path, 2, $LibVersion))
20384 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020385 $CheckHeadersOnly = 1;
20386
20387 if($LibVersion==1) {
20388 $TargetVersion{$LibVersion} = "X";
20389 }
20390
20391 if($LibVersion==2) {
20392 $TargetVersion{$LibVersion} = "Y";
20393 }
20394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020395 return "
20396 <version>
20397 ".$TargetVersion{$LibVersion}."
20398 </version>
20399
20400 <headers>
20401 $Path
20402 </headers>
20403
20404 <libs>
20405 none
20406 </libs>";
20407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020408 else
20409 { # standard XML-descriptor
20410 return readFile($Path);
20411 }
20412 }
20413}
20414
20415sub detect_lib_default_paths()
20416{
20417 my %LPaths = ();
20418 if($OSgroup eq "bsd")
20419 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020420 if(my $LdConfig = get_CmdPath("ldconfig"))
20421 {
20422 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20423 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020424 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20425 {
20426 my $Name = "lib".$1;
20427 if(not defined $LPaths{$Name}) {
20428 $LPaths{$Name} = $2;
20429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020430 }
20431 }
20432 }
20433 else {
20434 printMsg("WARNING", "can't find ldconfig");
20435 }
20436 }
20437 else
20438 {
20439 if(my $LdConfig = get_CmdPath("ldconfig"))
20440 {
20441 if($SystemRoot and $OSgroup eq "linux")
20442 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20443 if(-e $SystemRoot."/etc/ld.so.conf") {
20444 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20445 }
20446 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020447 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20448 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020449 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20450 {
20451 my ($Name, $Path) = ($1, $2);
20452 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020453 if(not defined $LPaths{$Name})
20454 { # get first element from the list of available paths
20455
20456 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20457 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20458 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20459
20460 $LPaths{$Name} = $Path;
20461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020462 }
20463 }
20464 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020465 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 printMsg("WARNING", "can't find ldconfig");
20467 }
20468 }
20469 return \%LPaths;
20470}
20471
20472sub detect_bin_default_paths()
20473{
20474 my $EnvPaths = $ENV{"PATH"};
20475 if($OSgroup eq "beos") {
20476 $EnvPaths.=":".$ENV{"BETOOLS"};
20477 }
20478 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020479 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020480 {
20481 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020482 next if(not $Path);
20483 if($SystemRoot
20484 and $Path=~/\A\Q$SystemRoot\E\//)
20485 { # do NOT use binaries from target system
20486 next;
20487 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020488 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020489 }
20490}
20491
20492sub detect_inc_default_paths()
20493{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020494 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020495 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020496 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020497 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020498 next if(index($Line, "/cc1plus ")!=-1);
20499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020500 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20501 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020502 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020503 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020504 if(index($Path, "c++")!=-1
20505 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020506 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020507 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 if(not defined $MAIN_CPP_DIR
20509 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20510 $MAIN_CPP_DIR = $Path;
20511 }
20512 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020513 elsif(index($Path, "gcc")!=-1) {
20514 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020515 }
20516 else
20517 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020518 if($Path=~/local[\/\\]+include/)
20519 { # local paths
20520 next;
20521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020522 if($SystemRoot
20523 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20524 { # The GCC include path for user headers is not a part of the system root
20525 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20526 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20527 next;
20528 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020529 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020530 }
20531 }
20532 }
20533 unlink("$TMP_DIR/empty.h");
20534 return %DPaths;
20535}
20536
20537sub detect_default_paths($)
20538{
20539 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20540 my $Search = $_[0];
20541 if($Search!~/inc/) {
20542 $HSearch = 0;
20543 }
20544 if($Search!~/lib/) {
20545 $LSearch = 0;
20546 }
20547 if($Search!~/bin/) {
20548 $BSearch = 0;
20549 }
20550 if($Search!~/gcc/) {
20551 $GSearch = 0;
20552 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020553 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020554 { # <search_headers> section of the XML descriptor
20555 # do NOT search for systems headers
20556 $HSearch = 0;
20557 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020558 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020559 { # <search_libs> section of the XML descriptor
20560 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020561 $LSearch = 0;
20562 }
20563 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20564 { # additional search paths
20565 next if($Type eq "include" and not $HSearch);
20566 next if($Type eq "lib" and not $LSearch);
20567 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020568 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020569 }
20570 if($OSgroup ne "windows")
20571 { # unix-like
20572 foreach my $Type ("include", "lib", "bin")
20573 { # automatic detection of system "devel" directories
20574 next if($Type eq "include" and not $HSearch);
20575 next if($Type eq "lib" and not $LSearch);
20576 next if($Type eq "bin" and not $BSearch);
20577 my ($UsrDir, $RootDir) = ("/usr", "/");
20578 if($SystemRoot and $Type ne "bin")
20579 { # 1. search for target headers and libraries
20580 # 2. use host commands: ldconfig, readelf, etc.
20581 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20582 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020583 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 if(-d $RootDir."/".$Type)
20585 { # if "/lib" is symbolic link
20586 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020587 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020588 }
20589 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020590 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 }
20592 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020593 if(-d $UsrDir)
20594 {
20595 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020596 if(-d $UsrDir."/".$Type)
20597 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020598 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020599 }
20600 }
20601 }
20602 }
20603 if($BSearch)
20604 {
20605 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020606 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020607 }
20608 # check environment variables
20609 if($OSgroup eq "beos")
20610 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020611 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020613 if($_ eq ".") {
20614 next;
20615 }
20616 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20617 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20618 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020619 }
20620 }
20621 if($HSearch)
20622 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020623 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20624 split(/:|;/, $ENV{"BEINCLUDES"})
20625 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020626 }
20627 if($LSearch)
20628 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020629 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20630 split(/:|;/, $ENV{"BELIBRARIES"}),
20631 split(/:|;/, $ENV{"LIBRARY_PATH"})
20632 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020633 }
20634 }
20635 if($LSearch)
20636 { # using linker to get system paths
20637 if(my $LPaths = detect_lib_default_paths())
20638 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020639 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020640 foreach my $Name (keys(%{$LPaths}))
20641 {
20642 if($SystemRoot
20643 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20644 { # wrong ldconfig configuration
20645 # check your <sysroot>/etc/ld.so.conf
20646 next;
20647 }
20648 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020649 if(my $Dir = get_dirname($LPaths->{$Name})) {
20650 $Dirs{$Dir} = 1;
20651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020652 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020653 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020654 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020655 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020656 }
20657 if($BSearch)
20658 {
20659 if($CrossGcc)
20660 { # --cross-gcc=arm-linux-gcc
20661 if(-e $CrossGcc)
20662 { # absolute or relative path
20663 $GCC_PATH = get_abs_path($CrossGcc);
20664 }
20665 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20666 { # command name
20667 $GCC_PATH = $CrossGcc;
20668 }
20669 else {
20670 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20671 }
20672 if($GCC_PATH=~/\s/) {
20673 $GCC_PATH = "\"".$GCC_PATH."\"";
20674 }
20675 }
20676 }
20677 if($GSearch)
20678 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020679 if(not $CrossGcc)
20680 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020681 $GCC_PATH = get_CmdPath("gcc");
20682 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020683 if(not $GCC_PATH)
20684 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020685 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020686 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020687 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020688 { # select the latest version
20689 @GCCs = sort {$b cmp $a} @GCCs;
20690 if(check_gcc($GCCs[0], "3"))
20691 {
20692 $GCC_PATH = $GCCs[0];
20693 last;
20694 }
20695 }
20696 }
20697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020698 if(not $GCC_PATH) {
20699 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20700 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020701
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020702 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020703 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020704 my $GccTarget = get_dumpmachine($GCC_PATH);
20705
20706 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020707 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020708 $OStarget = "linux";
20709 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020710 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020711 elsif($GccTarget=~/symbian/)
20712 {
20713 $OStarget = "symbian";
20714 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20715 }
20716
20717 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20718
20719 # check GCC version
20720 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20721 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20722 # introduced in 4.8
20723 # fixed in 4.8.3
20724 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20725 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020726 }
20727 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020728 else {
20729 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020730 }
20731 }
20732 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020733 {
20734 # GCC standard paths
20735 if($GCC_PATH and not $NoStdInc)
20736 {
20737 my %DPaths = detect_inc_default_paths();
20738 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20739 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20740 @DefaultIncPaths = @{$DPaths{"Inc"}};
20741 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20742 }
20743
20744 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020745 my $IncPath = "/usr/include";
20746 if($SystemRoot) {
20747 $IncPath = $SystemRoot.$IncPath;
20748 }
20749 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020750 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020751 }
20752 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020753
20754 if($ExtraInfo)
20755 {
20756 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20757 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020759}
20760
20761sub getLIB_EXT($)
20762{
20763 my $Target = $_[0];
20764 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20765 return $Ext;
20766 }
20767 return $OS_LibExt{$LIB_TYPE}{"default"};
20768}
20769
20770sub getAR_EXT($)
20771{
20772 my $Target = $_[0];
20773 if(my $Ext = $OS_Archive{$Target}) {
20774 return $Ext;
20775 }
20776 return $OS_Archive{"default"};
20777}
20778
20779sub get_dumpversion($)
20780{
20781 my $Cmd = $_[0];
20782 return "" if(not $Cmd);
20783 if($Cache{"get_dumpversion"}{$Cmd}) {
20784 return $Cache{"get_dumpversion"}{$Cmd};
20785 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020786 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 chomp($V);
20788 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20789}
20790
20791sub get_dumpmachine($)
20792{
20793 my $Cmd = $_[0];
20794 return "" if(not $Cmd);
20795 if($Cache{"get_dumpmachine"}{$Cmd}) {
20796 return $Cache{"get_dumpmachine"}{$Cmd};
20797 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020798 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020799 chomp($Machine);
20800 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20801}
20802
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020803sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020804{
20805 my $Cmd = $_[0];
20806 return "" if(not $Cmd);
20807 my @Options = (
20808 "--version",
20809 "-help"
20810 );
20811 foreach my $Opt (@Options)
20812 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020813 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020814 if($Info) {
20815 return 1;
20816 }
20817 }
20818 return 0;
20819}
20820
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020821sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020822{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020823 my ($Cmd, $ReqVer) = @_;
20824 return 0 if(not $Cmd or not $ReqVer);
20825 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20826 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020828 if(my $GccVer = get_dumpversion($Cmd))
20829 {
20830 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20831 if(cmpVersions($GccVer, $ReqVer)>=0) {
20832 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20833 }
20834 }
20835 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020836}
20837
20838sub get_depth($)
20839{
20840 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020841 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020842 }
20843 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20844}
20845
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020846sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020847{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020848 return if($Cache{"registerGccHeaders"}); # this function should be called once
20849
20850 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020851 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020852 my @Headers = cmd_find($Path,"f");
20853 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20854 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020855 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020856 my $FileName = get_filename($HPath);
20857 if(not defined $DefaultGccHeader{$FileName})
20858 { # skip duplicated
20859 $DefaultGccHeader{$FileName} = $HPath;
20860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020861 }
20862 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020863 $Cache{"registerGccHeaders"} = 1;
20864}
20865
20866sub registerCppHeaders()
20867{
20868 return if($Cache{"registerCppHeaders"}); # this function should be called once
20869
20870 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020871 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020872 my @Headers = cmd_find($CppDir,"f");
20873 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20874 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020875 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020876 my $FileName = get_filename($Path);
20877 if(not defined $DefaultCppHeader{$FileName})
20878 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020879 $DefaultCppHeader{$FileName} = $Path;
20880 }
20881 }
20882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020883 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020884}
20885
20886sub parse_libname($$$)
20887{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020888 return "" if(not $_[0]);
20889 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20890 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020891 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020892 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20893}
20894
20895sub parse_libname_I($$$)
20896{
20897 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020898
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020899 if($Target eq "symbian") {
20900 return parse_libname_symbian($Name, $Type);
20901 }
20902 elsif($Target eq "windows") {
20903 return parse_libname_windows($Name, $Type);
20904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020905
20906 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020907 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020908 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020909 { # libSDL-1.2.so.0.7.1
20910 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020911 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020912 if($Type eq "name")
20913 { # libSDL-1.2
20914 # libwbxml2
20915 return $2;
20916 }
20917 elsif($Type eq "name+ext")
20918 { # libSDL-1.2.so
20919 # libwbxml2.so
20920 return $1;
20921 }
20922 elsif($Type eq "version")
20923 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020924 if(defined $7
20925 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020926 { # 0.7.1
20927 return $7;
20928 }
20929 else
20930 { # libc-2.5.so (=>2.5 version)
20931 my $MV = $5;
20932 $MV=~s/\A[\-\_]+//g;
20933 return $MV;
20934 }
20935 }
20936 elsif($Type eq "short")
20937 { # libSDL
20938 # libwbxml2
20939 return $3;
20940 }
20941 elsif($Type eq "shortest")
20942 { # SDL
20943 # wbxml
20944 return shortest_name($3);
20945 }
20946 }
20947 return "";# error
20948}
20949
20950sub parse_libname_symbian($$)
20951{
20952 my ($Name, $Type) = @_;
20953 my $Ext = getLIB_EXT("symbian");
20954 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20955 { # libpthread{00010001}.dso
20956 if($Type eq "name")
20957 { # libpthread{00010001}
20958 return $2;
20959 }
20960 elsif($Type eq "name+ext")
20961 { # libpthread{00010001}.dso
20962 return $1;
20963 }
20964 elsif($Type eq "version")
20965 { # 00010001
20966 my $V = $4;
20967 $V=~s/\{(.+)\}/$1/;
20968 return $V;
20969 }
20970 elsif($Type eq "short")
20971 { # libpthread
20972 return $3;
20973 }
20974 elsif($Type eq "shortest")
20975 { # pthread
20976 return shortest_name($3);
20977 }
20978 }
20979 return "";# error
20980}
20981
20982sub parse_libname_windows($$)
20983{
20984 my ($Name, $Type) = @_;
20985 my $Ext = getLIB_EXT("windows");
20986 if($Name=~/((.+?)\.$Ext)\Z/)
20987 { # netapi32.dll
20988 if($Type eq "name")
20989 { # netapi32
20990 return $2;
20991 }
20992 elsif($Type eq "name+ext")
20993 { # netapi32.dll
20994 return $1;
20995 }
20996 elsif($Type eq "version")
20997 { # DLL version embedded
20998 # at binary-level
20999 return "";
21000 }
21001 elsif($Type eq "short")
21002 { # netapi32
21003 return $2;
21004 }
21005 elsif($Type eq "shortest")
21006 { # netapi
21007 return shortest_name($2);
21008 }
21009 }
21010 return "";# error
21011}
21012
21013sub shortest_name($)
21014{
21015 my $Name = $_[0];
21016 # remove prefix
21017 $Name=~s/\A(lib|open)//;
21018 # remove suffix
21019 $Name=~s/[\W\d_]+\Z//i;
21020 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21021 return $Name;
21022}
21023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021024sub createSymbolsList($$$$$)
21025{
21026 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021027
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021029 prepareSymbols(1);
21030
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021031 my %SymbolHeaderLib = ();
21032 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021034 # Get List
21035 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21036 {
21037 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021038 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021039 next;
21040 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021041 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 { # skip other symbols
21043 next;
21044 }
21045 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21046 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021047 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 next;
21049 }
21050 my $DyLib = $Symbol_Library{1}{$Symbol};
21051 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021052 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021053 next;
21054 }
21055 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21056 $Total+=1;
21057 }
21058 # Draw List
21059 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21060 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21061 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21062 {
21063 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21064 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021065 my %NS_Symbol = ();
21066 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021067 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021068 }
21069 foreach my $NameSpace (sort keys(%NS_Symbol))
21070 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021071 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021072 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21073 foreach my $Symbol (@SortedInterfaces)
21074 {
21075 my $SubReport = "";
21076 my $Signature = get_Signature($Symbol, 1);
21077 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021078 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021079 }
21080 if($Symbol=~/\A(_Z|\?)/)
21081 {
21082 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021083 $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 +040021084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021085 else {
21086 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21087 }
21088 }
21089 else
21090 {
21091 if($Signature) {
21092 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21093 }
21094 else {
21095 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21096 }
21097 }
21098 $SYMBOLS_LIST .= $SubReport;
21099 }
21100 }
21101 $SYMBOLS_LIST .= "<br/>\n";
21102 }
21103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021104 # clear info
21105 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21106 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21107 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21108 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021109 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021110 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021111 my $CssStyles = readModule("Styles", "SymbolsList.css");
21112 my $JScripts = readModule("Scripts", "Sections.js");
21113 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021114 my $Title = "$LName: public symbols";
21115 my $Keywords = "$LName, API, symbols";
21116 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021117 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021118 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021119 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021120 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021121 writeFile($SaveTo, $SYMBOLS_LIST);
21122}
21123
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021124sub add_target_libs($)
21125{
21126 foreach (@{$_[0]}) {
21127 $TargetLibs{$_} = 1;
21128 }
21129}
21130
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021131sub is_target_lib($)
21132{
21133 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021134 if(not $LName) {
21135 return 0;
21136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021137 if($TargetLibraryName
21138 and $LName!~/\Q$TargetLibraryName\E/) {
21139 return 0;
21140 }
21141 if(keys(%TargetLibs)
21142 and not $TargetLibs{$LName}
21143 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21144 return 0;
21145 }
21146 return 1;
21147}
21148
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021149sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021150{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021151 my ($H, $V) = @_;
21152 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021153 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021154 if($TargetHeaders{$V}{$H}) {
21155 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021156 }
21157 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021158 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159}
21160
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161sub readLibs($)
21162{
21163 my $LibVersion = $_[0];
21164 if($OStarget eq "windows")
21165 { # dumpbin.exe will crash
21166 # without VS Environment
21167 check_win32_env();
21168 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021169 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021170 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021171 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021172}
21173
21174sub dump_sorting($)
21175{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021176 my $Hash = $_[0];
21177 return [] if(not $Hash);
21178 my @Keys = keys(%{$Hash});
21179 return [] if($#Keys<0);
21180 if($Keys[0]=~/\A\d+\Z/)
21181 { # numbers
21182 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021183 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021184 else
21185 { # strings
21186 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021187 }
21188}
21189
21190sub printMsg($$)
21191{
21192 my ($Type, $Msg) = @_;
21193 if($Type!~/\AINFO/) {
21194 $Msg = $Type.": ".$Msg;
21195 }
21196 if($Type!~/_C\Z/) {
21197 $Msg .= "\n";
21198 }
21199 if($Quiet)
21200 { # --quiet option
21201 appendFile($COMMON_LOG_PATH, $Msg);
21202 }
21203 else
21204 {
21205 if($Type eq "ERROR") {
21206 print STDERR $Msg;
21207 }
21208 else {
21209 print $Msg;
21210 }
21211 }
21212}
21213
21214sub exitStatus($$)
21215{
21216 my ($Code, $Msg) = @_;
21217 printMsg("ERROR", $Msg);
21218 exit($ERROR_CODE{$Code});
21219}
21220
21221sub exitReport()
21222{ # the tool has run without any errors
21223 printReport();
21224 if($COMPILE_ERRORS)
21225 { # errors in headers may add false positives/negatives
21226 exit($ERROR_CODE{"Compile_Error"});
21227 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021228 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21229 { # --binary
21230 exit($ERROR_CODE{"Incompatible"});
21231 }
21232 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21233 { # --source
21234 exit($ERROR_CODE{"Incompatible"});
21235 }
21236 elsif($RESULT{"Source"}{"Problems"}
21237 or $RESULT{"Binary"}{"Problems"})
21238 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021239 exit($ERROR_CODE{"Incompatible"});
21240 }
21241 else {
21242 exit($ERROR_CODE{"Compatible"});
21243 }
21244}
21245
21246sub readRules($)
21247{
21248 my $Kind = $_[0];
21249 if(not -f $RULES_PATH{$Kind}) {
21250 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21251 }
21252 my $Content = readFile($RULES_PATH{$Kind});
21253 while(my $Rule = parseTag(\$Content, "rule"))
21254 {
21255 my $RId = parseTag(\$Rule, "id");
21256 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21257 foreach my $Prop (@Properties) {
21258 if(my $Value = parseTag(\$Rule, lc($Prop)))
21259 {
21260 $Value=~s/\n[ ]*//;
21261 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21262 }
21263 }
21264 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21265 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21266 }
21267 else {
21268 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21269 }
21270 }
21271}
21272
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021273sub getReportPath($)
21274{
21275 my $Level = $_[0];
21276 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21277 if($Level eq "Binary")
21278 {
21279 if($BinaryReportPath)
21280 { # --bin-report-path
21281 return $BinaryReportPath;
21282 }
21283 elsif($OutputReportPath)
21284 { # --report-path
21285 return $OutputReportPath;
21286 }
21287 else
21288 { # default
21289 return $Dir."/abi_compat_report.$ReportFormat";
21290 }
21291 }
21292 elsif($Level eq "Source")
21293 {
21294 if($SourceReportPath)
21295 { # --src-report-path
21296 return $SourceReportPath;
21297 }
21298 elsif($OutputReportPath)
21299 { # --report-path
21300 return $OutputReportPath;
21301 }
21302 else
21303 { # default
21304 return $Dir."/src_compat_report.$ReportFormat";
21305 }
21306 }
21307 else
21308 {
21309 if($OutputReportPath)
21310 { # --report-path
21311 return $OutputReportPath;
21312 }
21313 else
21314 { # default
21315 return $Dir."/compat_report.$ReportFormat";
21316 }
21317 }
21318}
21319
21320sub printStatMsg($)
21321{
21322 my $Level = $_[0];
21323 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21324}
21325
21326sub listAffected($)
21327{
21328 my $Level = $_[0];
21329 my $List = "";
21330 foreach (keys(%{$TotalAffected{$Level}}))
21331 {
21332 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21333 { # skip "Low"-severity problems
21334 next;
21335 }
21336 $List .= "$_\n";
21337 }
21338 my $Dir = get_dirname(getReportPath($Level));
21339 if($Level eq "Binary") {
21340 writeFile($Dir."/abi_affected.txt", $List);
21341 }
21342 elsif($Level eq "Source") {
21343 writeFile($Dir."/src_affected.txt", $List);
21344 }
21345}
21346
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021347sub printReport()
21348{
21349 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021350 createReport();
21351 if($JoinReport or $DoubleReport)
21352 {
21353 if($RESULT{"Binary"}{"Problems"}
21354 or $RESULT{"Source"}{"Problems"}) {
21355 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021356 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021357 else {
21358 printMsg("INFO", "result: COMPATIBLE");
21359 }
21360 printStatMsg("Binary");
21361 printStatMsg("Source");
21362 if($ListAffected)
21363 { # --list-affected
21364 listAffected("Binary");
21365 listAffected("Source");
21366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021367 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021368 elsif($BinaryOnly)
21369 {
21370 if($RESULT{"Binary"}{"Problems"}) {
21371 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21372 }
21373 else {
21374 printMsg("INFO", "result: COMPATIBLE");
21375 }
21376 printStatMsg("Binary");
21377 if($ListAffected)
21378 { # --list-affected
21379 listAffected("Binary");
21380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021382 elsif($SourceOnly)
21383 {
21384 if($RESULT{"Source"}{"Problems"}) {
21385 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21386 }
21387 else {
21388 printMsg("INFO", "result: COMPATIBLE");
21389 }
21390 printStatMsg("Source");
21391 if($ListAffected)
21392 { # --list-affected
21393 listAffected("Source");
21394 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021395 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021396 if($StdOut)
21397 {
21398 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021399 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021400 printMsg("INFO", "compatibility report has been generated to stdout");
21401 }
21402 else
21403 { # default
21404 printMsg("INFO", "compatibility reports have been generated to stdout");
21405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021406 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021407 else
21408 {
21409 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021410 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021411 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21412 }
21413 elsif($DoubleReport)
21414 { # default
21415 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21416 }
21417 elsif($BinaryOnly)
21418 { # --binary
21419 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21420 }
21421 elsif($SourceOnly)
21422 { # --source
21423 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021425 }
21426}
21427
21428sub check_win32_env()
21429{
21430 if(not $ENV{"DevEnvDir"}
21431 or not $ENV{"LIB"}) {
21432 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21433 }
21434}
21435
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021436sub diffSets($$)
21437{
21438 my ($S1, $S2) = @_;
21439 my @SK1 = keys(%{$S1});
21440 my @SK2 = keys(%{$S2});
21441 if($#SK1!=$#SK2) {
21442 return 1;
21443 }
21444 foreach my $K1 (@SK1)
21445 {
21446 if(not defined $S2->{$K1}) {
21447 return 1;
21448 }
21449 }
21450 return 0;
21451}
21452
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021453sub defaultDumpPath($$)
21454{
21455 my ($N, $V) = @_;
21456 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21457}
21458
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021459sub create_ABI_Dump()
21460{
21461 if(not -e $DumpAPI) {
21462 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21463 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021464
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021465 if(isDump($DumpAPI)) {
21466 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021467 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021468 else {
21469 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021470 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021471
21472 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021473 { # set to default: N
21474 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021475 }
21476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021477 initLogging(1);
21478 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021479
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021480 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021481 if($OutputDumpPath)
21482 { # user defined path
21483 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021484 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021485 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21486
21487 if(not $Archive and not $StdOut)
21488 { # check archive utilities
21489 if($OSgroup eq "windows")
21490 { # using zip
21491 my $ZipCmd = get_CmdPath("zip");
21492 if(not $ZipCmd) {
21493 exitStatus("Not_Found", "can't find \"zip\"");
21494 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021495 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021496 else
21497 { # using tar and gzip
21498 my $TarCmd = get_CmdPath("tar");
21499 if(not $TarCmd) {
21500 exitStatus("Not_Found", "can't find \"tar\"");
21501 }
21502 my $GzipCmd = get_CmdPath("gzip");
21503 if(not $GzipCmd) {
21504 exitStatus("Not_Found", "can't find \"gzip\"");
21505 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021506 }
21507 }
21508
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021509 if(not $Descriptor{1}{"Dump"})
21510 {
21511 if(not $CheckHeadersOnly) {
21512 readLibs(1);
21513 }
21514 if($CheckHeadersOnly) {
21515 setLanguage(1, "C++");
21516 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021517 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021518 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021519 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021520 if(not $Descriptor{1}{"Dump"})
21521 {
21522 if($Descriptor{1}{"Headers"}) {
21523 readHeaders(1);
21524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021525 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021526 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021527 if(not keys(%{$SymbolInfo{1}}))
21528 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021529 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021530 {
21531 if($CheckHeadersOnly) {
21532 exitStatus("Empty_Set", "the set of public symbols is empty");
21533 }
21534 else {
21535 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21536 }
21537 }
21538 }
21539 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021540 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021541 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21542 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021543 if($ExtraDump)
21544 { # add unmangled names to the ABI dump
21545 my @Names = ();
21546 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21547 {
21548 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21549 push(@Names, $MnglName);
21550 }
21551 }
21552 translateSymbols(@Names, 1);
21553 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21554 {
21555 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21556 {
21557 if(my $Unmangled = $tr_name{$MnglName})
21558 {
21559 if($MnglName ne $Unmangled) {
21560 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21561 }
21562 }
21563 }
21564 }
21565 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021566
21567 my %GccConstants = (); # built-in GCC constants
21568 foreach my $Name (keys(%{$Constants{1}}))
21569 {
21570 if(not defined $Constants{1}{$Name}{"Header"})
21571 {
21572 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21573 delete($Constants{1}{$Name});
21574 }
21575 }
21576
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021577 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021578 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021579 "TypeInfo" => $TypeInfo{1},
21580 "SymbolInfo" => $SymbolInfo{1},
21581 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021582 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021583 "SymbolVersion" => $SymVer{1},
21584 "LibraryVersion" => $Descriptor{1}{"Version"},
21585 "LibraryName" => $TargetLibraryName,
21586 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021587 "SkipTypes" => $SkipTypes{1},
21588 "SkipSymbols" => $SkipSymbols{1},
21589 "SkipNameSpaces" => $SkipNameSpaces{1},
21590 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021591 "Headers" => \%HeadersInfo,
21592 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021593 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594 "NameSpaces" => $NestedNameSpaces{1},
21595 "Target" => $OStarget,
21596 "Arch" => getArch(1),
21597 "WordSize" => $WORD_SIZE{1},
21598 "GccVersion" => get_dumpversion($GCC_PATH),
21599 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21600 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21601 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021602 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021603 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021604 }
21605 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021606 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021608 if($ExtendedCheck)
21609 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021610 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021612 if($BinaryOnly)
21613 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021614 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021615 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021616 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021617 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021618 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021619 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21620 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021621 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021622
21623 my $ABI_DUMP = "";
21624 if($UseXML)
21625 {
21626 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021627 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021628 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021629 else
21630 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021631 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021633 if($StdOut)
21634 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021635 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021636 printMsg("INFO", "ABI dump has been generated to stdout");
21637 return;
21638 }
21639 else
21640 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021641 my ($DDir, $DName) = separate_path($DumpPath);
21642 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021643 if(not $Archive) {
21644 $DPath = $DumpPath;
21645 }
21646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021647 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021648
21649 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021650 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021651 close(DUMP);
21652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021653 if(not -s $DPath) {
21654 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21655 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021656 if($Archive) {
21657 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021658 }
21659
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021660 if($OutputDumpPath) {
21661 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021662 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021663 else {
21664 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21665 }
21666 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 +040021667 }
21668}
21669
21670sub quickEmptyReports()
21671{ # Quick "empty" reports
21672 # 4 times faster than merging equal dumps
21673 # NOTE: the dump contains the "LibraryVersion" attribute
21674 # if you change the version, then your dump will be different
21675 # OVERCOME: use -v1 and v2 options for comparing dumps
21676 # and don't change version in the XML descriptor (and dumps)
21677 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21678 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21679 {
21680 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21681 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21682 if($FilePath1 and $FilePath2)
21683 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021684 my $Line = readLineNum($FilePath1, 0);
21685 if($Line=~/xml/)
21686 { # XML format
21687 # is not supported yet
21688 return;
21689 }
21690
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021691 local $/ = undef;
21692
21693 open(DUMP1, $FilePath1);
21694 my $Content1 = <DUMP1>;
21695 close(DUMP1);
21696
21697 open(DUMP2, $FilePath2);
21698 my $Content2 = <DUMP2>;
21699 close(DUMP2);
21700
21701 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021702 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021703 # clean memory
21704 undef $Content2;
21705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021706 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021707 my $ABIdump = eval($Content1);
21708
21709 # clean memory
21710 undef $Content1;
21711
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021712 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021713 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 +040021714 }
21715 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021716 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021717 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21718 }
21719 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021720 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021721 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21722 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021723 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021724 read_Libs_DumpInfo($ABIdump, 1);
21725 read_Machine_DumpInfo($ABIdump, 1);
21726 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021727
21728 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21729 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21730
21731 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21732 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21733
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021734 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21735 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21736 exitReport();
21737 }
21738 }
21739 }
21740}
21741
21742sub initLogging($)
21743{
21744 my $LibVersion = $_[0];
21745 # create log directory
21746 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21747 if($OutputLogPath{$LibVersion})
21748 { # user-defined by -log-path option
21749 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21750 }
21751 if($LogMode ne "n") {
21752 mkpath($LOG_DIR);
21753 }
21754 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021755 if($Debug)
21756 { # debug directory
21757 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021758
21759 if(not $ExtraInfo)
21760 { # enable --extra-info
21761 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021763 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021764 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021765}
21766
21767sub writeLog($$)
21768{
21769 my ($LibVersion, $Msg) = @_;
21770 if($LogMode ne "n") {
21771 appendFile($LOG_PATH{$LibVersion}, $Msg);
21772 }
21773}
21774
21775sub resetLogging($)
21776{
21777 my $LibVersion = $_[0];
21778 if($LogMode!~/a|n/)
21779 { # remove old log
21780 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021781 if($Debug) {
21782 rmtree($DEBUG_PATH{$LibVersion});
21783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021784 }
21785}
21786
21787sub printErrorLog($)
21788{
21789 my $LibVersion = $_[0];
21790 if($LogMode ne "n") {
21791 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21792 }
21793}
21794
21795sub isDump($)
21796{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021797 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21798 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021799 return $1;
21800 }
21801 return 0;
21802}
21803
21804sub isDump_U($)
21805{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021806 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021807 return $1;
21808 }
21809 return 0;
21810}
21811
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021812sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021813{
21814 # read input XML descriptors or ABI dumps
21815 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021816 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021817 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021818 if(not -e $Descriptor{1}{"Path"}) {
21819 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021820 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021822 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021823 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021824 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021825 if(not -e $Descriptor{2}{"Path"}) {
21826 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021827 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021828
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021829 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021830 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021831 and isDump($Descriptor{2}{"Path"}))
21832 { # optimization: equal ABI dumps
21833 quickEmptyReports();
21834 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021836 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021837
21838 if(isDump($Descriptor{1}{"Path"})) {
21839 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021840 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021841 else {
21842 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21843 }
21844
21845 if(isDump($Descriptor{2}{"Path"})) {
21846 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21847 }
21848 else {
21849 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021850 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021851
21852 if(not $Descriptor{1}{"Version"})
21853 { # set to default: X
21854 $Descriptor{1}{"Version"} = "X";
21855 }
21856
21857 if(not $Descriptor{2}{"Version"})
21858 { # set to default: Y
21859 $Descriptor{2}{"Version"} = "Y";
21860 }
21861
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021862 initLogging(1);
21863 initLogging(2);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021864
21865 # check input data
21866 if(not $Descriptor{1}{"Headers"}) {
21867 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021868 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021869 if(not $Descriptor{2}{"Headers"}) {
21870 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021872
21873 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021874 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021875 if(not $Descriptor{1}{"Libs"}) {
21876 exitStatus("Error", "can't find libraries info in descriptor d1");
21877 }
21878 if(not $Descriptor{2}{"Libs"}) {
21879 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021880 }
21881 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021882
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021883 if($UseDumps)
21884 { # --use-dumps
21885 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021886 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21887 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021888
21889 unlink($DumpPath1);
21890 unlink($DumpPath2);
21891
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021892 my $pid = fork();
21893 if($pid)
21894 { # dump on two CPU cores
21895 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21896 if($RelativeDirectory{1}) {
21897 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21898 }
21899 if($OutputLogPath{1}) {
21900 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21901 }
21902 if($CrossGcc) {
21903 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21904 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021905 if($Quiet)
21906 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021907 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021908 @PARAMS = (@PARAMS, "-logging-mode", "a");
21909 }
21910 elsif($LogMode and $LogMode ne "w")
21911 { # "w" is default
21912 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021913 }
21914 if($ExtendedCheck) {
21915 @PARAMS = (@PARAMS, "-extended");
21916 }
21917 if($UserLang) {
21918 @PARAMS = (@PARAMS, "-lang", $UserLang);
21919 }
21920 if($TargetVersion{1}) {
21921 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21922 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021923 if($BinaryOnly) {
21924 @PARAMS = (@PARAMS, "-binary");
21925 }
21926 if($SourceOnly) {
21927 @PARAMS = (@PARAMS, "-source");
21928 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021929 if($SortDump) {
21930 @PARAMS = (@PARAMS, "-sort");
21931 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021932 if($DumpFormat and $DumpFormat ne "perl") {
21933 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21934 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021935 if($CheckHeadersOnly) {
21936 @PARAMS = (@PARAMS, "-headers-only");
21937 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021938 if($Debug)
21939 {
21940 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021941 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021943 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021944 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021945 exit(1);
21946 }
21947 }
21948 else
21949 { # child
21950 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21951 if($RelativeDirectory{2}) {
21952 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21953 }
21954 if($OutputLogPath{2}) {
21955 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21956 }
21957 if($CrossGcc) {
21958 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21959 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021960 if($Quiet)
21961 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021962 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021963 @PARAMS = (@PARAMS, "-logging-mode", "a");
21964 }
21965 elsif($LogMode and $LogMode ne "w")
21966 { # "w" is default
21967 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021968 }
21969 if($ExtendedCheck) {
21970 @PARAMS = (@PARAMS, "-extended");
21971 }
21972 if($UserLang) {
21973 @PARAMS = (@PARAMS, "-lang", $UserLang);
21974 }
21975 if($TargetVersion{2}) {
21976 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21977 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021978 if($BinaryOnly) {
21979 @PARAMS = (@PARAMS, "-binary");
21980 }
21981 if($SourceOnly) {
21982 @PARAMS = (@PARAMS, "-source");
21983 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021984 if($SortDump) {
21985 @PARAMS = (@PARAMS, "-sort");
21986 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021987 if($DumpFormat and $DumpFormat ne "perl") {
21988 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21989 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021990 if($CheckHeadersOnly) {
21991 @PARAMS = (@PARAMS, "-headers-only");
21992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021993 if($Debug)
21994 {
21995 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021996 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021998 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021999 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022000 exit(1);
22001 }
22002 else {
22003 exit(0);
22004 }
22005 }
22006 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022007
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022008 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022009 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22010 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022011 if($TargetTitle ne $TargetLibraryName) {
22012 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022013 }
22014 if($ShowRetVal) {
22015 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22016 }
22017 if($CrossGcc) {
22018 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22019 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022020 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22021 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022022 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022023 }
22024 if($ReportFormat and $ReportFormat ne "html")
22025 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022026 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22027 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022028 if($OutputReportPath) {
22029 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22030 }
22031 if($BinaryReportPath) {
22032 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22033 }
22034 if($SourceReportPath) {
22035 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22036 }
22037 if($LoggingPath) {
22038 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22039 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022040 if($CheckHeadersOnly) {
22041 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22042 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022043 if($BinaryOnly) {
22044 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22045 }
22046 if($SourceOnly) {
22047 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22048 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022049 if($Debug)
22050 {
22051 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22052 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022054 system("perl", $0, @CMP_PARAMS);
22055 exit($?>>8);
22056 }
22057 if(not $Descriptor{1}{"Dump"}
22058 or not $Descriptor{2}{"Dump"})
22059 { # need GCC toolchain to analyze
22060 # header files and libraries
22061 detect_default_paths("inc|lib|gcc");
22062 }
22063 if(not $Descriptor{1}{"Dump"})
22064 {
22065 if(not $CheckHeadersOnly) {
22066 readLibs(1);
22067 }
22068 if($CheckHeadersOnly) {
22069 setLanguage(1, "C++");
22070 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022071 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022072 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022073 }
22074 if(not $Descriptor{2}{"Dump"})
22075 {
22076 if(not $CheckHeadersOnly) {
22077 readLibs(2);
22078 }
22079 if($CheckHeadersOnly) {
22080 setLanguage(2, "C++");
22081 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022082 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022083 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022084 }
22085 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22086 { # support for old ABI dumps
22087 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022088 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022089 {
22090 $WORD_SIZE{1} = $WORD_SIZE{2};
22091 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022093 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022094 {
22095 $WORD_SIZE{2} = $WORD_SIZE{1};
22096 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22097 }
22098 }
22099 elsif(not $WORD_SIZE{1}
22100 and not $WORD_SIZE{2})
22101 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022102 $WORD_SIZE{1} = "4";
22103 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022104 }
22105 if($Descriptor{1}{"Dump"})
22106 { # support for old ABI dumps
22107 prepareTypes(1);
22108 }
22109 if($Descriptor{2}{"Dump"})
22110 { # support for old ABI dumps
22111 prepareTypes(2);
22112 }
22113 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22114 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22115 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022116 # process input data
22117 if($Descriptor{1}{"Headers"}
22118 and not $Descriptor{1}{"Dump"}) {
22119 readHeaders(1);
22120 }
22121 if($Descriptor{2}{"Headers"}
22122 and not $Descriptor{2}{"Dump"}) {
22123 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022124 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022125
22126 # clean memory
22127 %SystemHeaders = ();
22128 %mangled_name_gcc = ();
22129
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022130 prepareSymbols(1);
22131 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022132
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022133 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022134 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022135
22136 # Virtual Tables
22137 registerVTable(1);
22138 registerVTable(2);
22139
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022140 if(not checkDump(1, "1.22")
22141 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022142 { # support for old ABI dumps
22143 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22144 {
22145 if($ClassName=~/</)
22146 { # templates
22147 if(not defined $VirtualTable{1}{$ClassName})
22148 { # synchronize
22149 delete($VirtualTable{2}{$ClassName});
22150 }
22151 }
22152 }
22153 }
22154
22155 registerOverriding(1);
22156 registerOverriding(2);
22157
22158 setVirtFuncPositions(1);
22159 setVirtFuncPositions(2);
22160
22161 # Other
22162 addParamNames(1);
22163 addParamNames(2);
22164
22165 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022166}
22167
22168sub compareAPIs($)
22169{
22170 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022171
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022172 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022173 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022174
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022175 if($Level eq "Binary") {
22176 printMsg("INFO", "comparing ABIs ...");
22177 }
22178 else {
22179 printMsg("INFO", "comparing APIs ...");
22180 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022181
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022182 if($CheckHeadersOnly
22183 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022184 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022185 detectAdded_H($Level);
22186 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022187 }
22188 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022189 { # added/removed in libs
22190 detectAdded($Level);
22191 detectRemoved($Level);
22192 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022193
22194 mergeSymbols($Level);
22195 if(keys(%{$CheckedSymbols{$Level}})) {
22196 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022197 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022198
22199 $Cache{"mergeTypes"} = (); # free memory
22200
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022201 if($CheckHeadersOnly
22202 or $Level eq "Source")
22203 { # added/removed in headers
22204 mergeHeaders($Level);
22205 }
22206 else
22207 { # added/removed in libs
22208 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022209 }
22210}
22211
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022212sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022213{
22214 my %Opts = (
22215 "OStarget"=>$OStarget,
22216 "Debug"=>$Debug,
22217 "Quiet"=>$Quiet,
22218 "LogMode"=>$LogMode,
22219 "CheckHeadersOnly"=>$CheckHeadersOnly,
22220
22221 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022222 "GCC_PATH"=>$GCC_PATH,
22223 "TargetSysInfo"=>$TargetSysInfo,
22224 "CrossPrefix"=>$CrossPrefix,
22225 "TargetLibraryName"=>$TargetLibraryName,
22226 "CrossGcc"=>$CrossGcc,
22227 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022228 "NoStdInc"=>$NoStdInc,
22229
22230 "BinaryOnly" => $BinaryOnly,
22231 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022232 );
22233 return \%Opts;
22234}
22235
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022236sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022237{
22238 my %CODE_ERROR = reverse(%ERROR_CODE);
22239 return $CODE_ERROR{$_[0]};
22240}
22241
22242sub scenario()
22243{
22244 if($StdOut)
22245 { # enable quiet mode
22246 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022247 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022248 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022249 if(not $LogMode)
22250 { # default
22251 $LogMode = "w";
22252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022253 if($UserLang)
22254 { # --lang=C++
22255 $UserLang = uc($UserLang);
22256 $COMMON_LANGUAGE{1}=$UserLang;
22257 $COMMON_LANGUAGE{2}=$UserLang;
22258 }
22259 if($LoggingPath)
22260 {
22261 $OutputLogPath{1} = $LoggingPath;
22262 $OutputLogPath{2} = $LoggingPath;
22263 if($Quiet) {
22264 $COMMON_LOG_PATH = $LoggingPath;
22265 }
22266 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022267 if($Quick) {
22268 $ADD_TMPL_INSTANCES = 0;
22269 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022270 if($OutputDumpPath)
22271 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022272 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022273 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22274 }
22275 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022276 if($BinaryOnly and $SourceOnly)
22277 { # both --binary and --source
22278 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022279 if(not $CmpSystems)
22280 {
22281 $BinaryOnly = 0;
22282 $SourceOnly = 0;
22283 }
22284
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022285 $DoubleReport = 1;
22286 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022287
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022288 if($OutputReportPath)
22289 { # --report-path
22290 $DoubleReport = 0;
22291 $JoinReport = 1;
22292 }
22293 }
22294 elsif($BinaryOnly or $SourceOnly)
22295 { # --binary or --source
22296 $DoubleReport = 0;
22297 $JoinReport = 0;
22298 }
22299 if($UseXML)
22300 { # --xml option
22301 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022302 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022304 if($ReportFormat)
22305 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022306 $ReportFormat = lc($ReportFormat);
22307 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022308 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022309 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022310 if($ReportFormat eq "htm")
22311 { # HTM == HTML
22312 $ReportFormat = "html";
22313 }
22314 elsif($ReportFormat eq "xml")
22315 { # --report-format=XML equal to --xml
22316 $UseXML = 1;
22317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022318 }
22319 else
22320 { # default: HTML
22321 $ReportFormat = "html";
22322 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022323 if($DumpFormat)
22324 { # validate
22325 $DumpFormat = lc($DumpFormat);
22326 if($DumpFormat!~/\A(xml|perl)\Z/) {
22327 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22328 }
22329 if($DumpFormat eq "xml")
22330 { # --dump-format=XML equal to --xml
22331 $UseXML = 1;
22332 }
22333 }
22334 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022335 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022336 $DumpFormat = "perl";
22337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022338 if($Quiet and $LogMode!~/a|n/)
22339 { # --quiet log
22340 if(-f $COMMON_LOG_PATH) {
22341 unlink($COMMON_LOG_PATH);
22342 }
22343 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022344 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022345 $CheckUndefined = 1;
22346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022347 if($TestTool and $UseDumps)
22348 { # --test && --use-dumps == --test-dump
22349 $TestDump = 1;
22350 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022351 if($Tolerant)
22352 { # enable all
22353 $Tolerance = 1234;
22354 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022355 if($Help)
22356 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022357 HELP_MESSAGE();
22358 exit(0);
22359 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022360 if($InfoMsg)
22361 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022362 INFO_MESSAGE();
22363 exit(0);
22364 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022365 if($ShowVersion)
22366 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022367 printMsg("INFO", "ABI Compliance Checker (ABICC) $TOOL_VERSION\nCopyright (C) 2015 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 +040022368 exit(0);
22369 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022370 if($DumpVersion)
22371 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022372 printMsg("INFO", $TOOL_VERSION);
22373 exit(0);
22374 }
22375 if($ExtendedCheck) {
22376 $CheckHeadersOnly = 1;
22377 }
22378 if($SystemRoot_Opt)
22379 { # user defined root
22380 if(not -e $SystemRoot_Opt) {
22381 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22382 }
22383 $SystemRoot = $SystemRoot_Opt;
22384 $SystemRoot=~s/[\/]+\Z//g;
22385 if($SystemRoot) {
22386 $SystemRoot = get_abs_path($SystemRoot);
22387 }
22388 }
22389 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022390
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022391 if($SortDump)
22392 {
22393 $Data::Dumper::Useperl = 1;
22394 $Data::Dumper::Sortkeys = \&dump_sorting;
22395 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022397 if($TargetLibsPath)
22398 {
22399 if(not -f $TargetLibsPath) {
22400 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22401 }
22402 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22403 $TargetLibs{$Lib} = 1;
22404 }
22405 }
22406 if($TargetHeadersPath)
22407 { # --headers-list
22408 if(not -f $TargetHeadersPath) {
22409 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22410 }
22411 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22412 {
22413 $TargetHeaders{1}{$Header} = 1;
22414 $TargetHeaders{2}{$Header} = 1;
22415 }
22416 }
22417 if($TargetHeader)
22418 { # --header
22419 $TargetHeaders{1}{$TargetHeader} = 1;
22420 $TargetHeaders{2}{$TargetHeader} = 1;
22421 }
22422 if($TestTool
22423 or $TestDump)
22424 { # --test, --test-dump
22425 detect_default_paths("bin|gcc"); # to compile libs
22426 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022427 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022428 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022429 exit(0);
22430 }
22431 if($DumpSystem)
22432 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022433
22434 if(not $TargetSysInfo) {
22435 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22436 }
22437
22438 if(not -d $TargetSysInfo) {
22439 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22440 }
22441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022443 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022444 { # system XML descriptor
22445 if(not -f $DumpSystem) {
22446 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22447 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022448
22449 my $SDesc = readFile($DumpSystem);
22450 if(my $RelDir = $RelativeDirectory{1}) {
22451 $SDesc =~ s/{RELPATH}/$RelDir/g;
22452 }
22453
22454 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022455 foreach (@{$Ret->{"Tools"}})
22456 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022457 push_U($SystemPaths{"bin"}, $_);
22458 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022459 }
22460 if($Ret->{"CrossPrefix"}) {
22461 $CrossPrefix = $Ret->{"CrossPrefix"};
22462 }
22463 }
22464 elsif($SystemRoot_Opt)
22465 { # -sysroot "/" option
22466 # default target: /usr/lib, /usr/include
22467 # search libs: /usr/lib and /lib
22468 if(not -e $SystemRoot."/usr/lib") {
22469 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22470 }
22471 if(not -e $SystemRoot."/lib") {
22472 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22473 }
22474 if(not -e $SystemRoot."/usr/include") {
22475 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22476 }
22477 readSystemDescriptor("
22478 <name>
22479 $DumpSystem
22480 </name>
22481 <headers>
22482 $SystemRoot/usr/include
22483 </headers>
22484 <libs>
22485 $SystemRoot/usr/lib
22486 </libs>
22487 <search_libs>
22488 $SystemRoot/lib
22489 </search_libs>");
22490 }
22491 else {
22492 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22493 }
22494 detect_default_paths("bin|gcc"); # to check symbols
22495 if($OStarget eq "windows")
22496 { # to run dumpbin.exe
22497 # and undname.exe
22498 check_win32_env();
22499 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022500 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022501 exit(0);
22502 }
22503 if($CmpSystems)
22504 { # --cmp-systems
22505 detect_default_paths("bin"); # to extract dumps
22506 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022507 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022508 exit(0);
22509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022510 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022511 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022512 }
22513 else
22514 { # validate library name
22515 if($TargetLibraryName=~/[\*\/\\]/) {
22516 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22517 }
22518 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022519 if(not $TargetTitle) {
22520 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022521 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022523 if($SymbolsListPath)
22524 {
22525 if(not -f $SymbolsListPath) {
22526 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22527 }
22528 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22529 $SymbolsList{$Interface} = 1;
22530 }
22531 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022532 if($TypesListPath)
22533 {
22534 if(not -f $TypesListPath) {
22535 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22536 }
22537 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22538 $TypesList{$Type} = 1;
22539 }
22540 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022541 if($SkipSymbolsListPath)
22542 {
22543 if(not -f $SkipSymbolsListPath) {
22544 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22545 }
22546 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022547 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022548 }
22549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022550 if($SkipHeadersPath)
22551 {
22552 if(not -f $SkipHeadersPath) {
22553 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22554 }
22555 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022556 { # register for both versions
22557 $SkipHeadersList{1}{$Path} = 1;
22558 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 my ($CPath, $Type) = classifyPath($Path);
22560 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022561 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022562 }
22563 }
22564 if($ParamNamesPath)
22565 {
22566 if(not -f $ParamNamesPath) {
22567 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22568 }
22569 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22570 {
22571 if($Line=~s/\A(\w+)\;//)
22572 {
22573 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022574 if($Line=~/;(\d+);/)
22575 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022576 while($Line=~s/(\d+);(\w+)//) {
22577 $AddIntParams{$Interface}{$1}=$2;
22578 }
22579 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022580 else
22581 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022582 my $Num = 0;
22583 foreach my $Name (split(/;/, $Line)) {
22584 $AddIntParams{$Interface}{$Num++}=$Name;
22585 }
22586 }
22587 }
22588 }
22589 }
22590 if($AppPath)
22591 {
22592 if(not -f $AppPath) {
22593 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22594 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022595
22596 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022597 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022598 $SymbolsList_App{$Interface} = 1;
22599 }
22600 }
22601 if($DumpAPI)
22602 { # --dump-abi
22603 # make an API dump
22604 create_ABI_Dump();
22605 exit($COMPILE_ERRORS);
22606 }
22607 # default: compare APIs
22608 # -d1 <path>
22609 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022610 compareInit();
22611 if($JoinReport or $DoubleReport)
22612 {
22613 compareAPIs("Binary");
22614 compareAPIs("Source");
22615 }
22616 elsif($BinaryOnly) {
22617 compareAPIs("Binary");
22618 }
22619 elsif($SourceOnly) {
22620 compareAPIs("Source");
22621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022622 exitReport();
22623}
22624
22625scenario();